Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Targets Exploration View, Problems Tab Updates #53

Merged
merged 4 commits into from
Oct 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions ent/gen/ent/gql_collection.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

47 changes: 47 additions & 0 deletions ent/gen/ent/gql_pagination.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 20 additions & 4 deletions ent/schema/targetpair.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package schema

import (
"entgo.io/contrib/entgql"
"entgo.io/ent"
"entgo.io/ent/schema"
"entgo.io/ent/schema/edge"
"entgo.io/ent/schema/field"
)
Expand All @@ -15,17 +17,23 @@ type TargetPair struct {
func (TargetPair) Fields() []ent.Field {
return []ent.Field{
// The label of the target ex: //foo:bar.
field.String("label").Optional(),
field.String("label").
Optional(),

// Duration in Milliseconds.
// Time from target configured message received and processed until target completed message received and processed, calculated on build complete
field.Int64("duration_in_ms").Optional(),
field.Int64("duration_in_ms").
Optional().
Annotations(entgql.OrderField("DURATION")),

// Overall success of the target (defaults to false).
field.Bool("success").Optional().Default(false),
field.Bool("success").
Optional().
Default(false),

// The target kind if available.
field.String("target_kind").Optional(),
field.String("target_kind").
Optional(),

// The size of the test, if the target is a test target. Unset otherwise.
field.Enum("test_size").
Expand Down Expand Up @@ -72,3 +80,11 @@ func (TargetPair) Edges() []ent.Edge {
Unique(),
}
}

// Annotations of the TargetPair
func (TargetPair) Annotations() []schema.Annotation {
return []schema.Annotation{
entgql.RelayConnection(),
entgql.QueryField("findTargets"),
}
}
26 changes: 21 additions & 5 deletions frontend/src/app/bazel-invocations/[invocationID]/index.graphql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,24 @@ export const LOAD_FULL_BAZEL_INVOCATION_DETAILS = gql(/* GraphQL */ `
}
`);

export const GET_PROBLEM_DETAILS = gql(/* GraphQL */ `
query GetProblemDetails($invocationID: String!) {
bazelInvocation(invocationId: $invocationID) {
...ProblemDetails
}
}
`);

export const PROBLEM_DETAILS_FRAGMENT = gql(/* GraphQL */`

fragment ProblemDetails on BazelInvocation{
problems {
...ProblemInfo
}
}

`)

export const BAZEL_INVOCATION_FRAGMENT = gql(/* GraphQL */ `
fragment BazelInvocationInfo on BazelInvocation {
metrics {
Expand Down Expand Up @@ -212,6 +230,9 @@ fragment BazelInvocationInfo on BazelInvocation {
}
id
}
configurationMnemonic
cpu
numFetches
stepLabel
sourceControl {
id
Expand Down Expand Up @@ -287,16 +308,11 @@ fragment BlobReferenceInfo on BlobReference {

export const FULL_BAZEL_INVOCATION_DETAILS = gql(/* GraphQL */ `
fragment FullBazelInvocationDetails on BazelInvocation {
problems {
...ProblemInfo
}
...BazelInvocationInfo
}
`);




export const GET_ACTION_PROBLEM = gql(/* GraphQL */ `
query GetActionProblem($id: ID!) {
node(id: $id) {
Expand Down
16 changes: 8 additions & 8 deletions frontend/src/app/bazel-invocations/[invocationID]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ const BazelInvocationsContent: React.FC<Props> = ({ loading, error, networkStatu
</Spin>
);
}
if (loading && networkStatus !== NetworkStatus.poll) {
return (
<Spin />
);
}
if (error && invocationInfo) {
return (
<>
Expand All @@ -50,12 +55,7 @@ const BazelInvocationsContent: React.FC<Props> = ({ loading, error, networkStatu
}

if (invocationInfo) {
return <BazelInvocation invocationOverview={invocationInfo}>
<BuildProblems
problems={problems}
/>
</BazelInvocation>

return <BazelInvocation invocationOverview={invocationInfo} />
}

return <></>
Expand All @@ -78,7 +78,7 @@ const Page: React.FC<PageParams> = ({ params }) => {

const invocation = getFragmentData(FULL_BAZEL_INVOCATION_DETAILS, data?.bazelInvocation);
const invocationOverview = getFragmentData(BAZEL_INVOCATION_FRAGMENT, invocation)
const problems = invocation?.problems.map(p => getFragmentData(PROBLEM_INFO_FRAGMENT, p))


const stop = shouldStopPolling(invocation);
useEffect(() => {
Expand All @@ -91,7 +91,7 @@ const Page: React.FC<PageParams> = ({ params }) => {

return (
<Content
content={<BazelInvocationsContent loading={loading} error={error} networkStatus={networkStatus} invocationInfo={invocationOverview as BazelInvocationInfoFragment} problems={problems ?? []} />}
content={<BazelInvocationsContent loading={loading} error={error} networkStatus={networkStatus} invocationInfo={invocationOverview as BazelInvocationInfoFragment} problems={[]} />}
/>
);
}
Expand Down
Empty file.
34 changes: 34 additions & 0 deletions frontend/src/app/targets/[slug]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
'use client';

import React from 'react';
import Content from '@/components/Content';
import PortalCard from '@/components/PortalCard';
import { Space } from 'antd';
import { DeploymentUnitOutlined } from '@ant-design/icons';
import TargetDetails from '@/components/Targets/TargetDetails';

interface PageParams {
params: {
slug: string
}
}

const Page: React.FC<PageParams> = ({ params }) => {
const label = decodeURIComponent(atob(decodeURIComponent(params.slug)))
return (
<Content
content={
<Space direction="vertical" size="middle" style={{ display: 'flex' }}>
<PortalCard
icon={<DeploymentUnitOutlined />}
titleBits={[<span key="title">Target Details</span>]}
>
<TargetDetails label={label} />
</PortalCard>
</Space >
}
/>
);
}

export default Page;
61 changes: 61 additions & 0 deletions frontend/src/app/targets/graphql.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { gql } from "@/graphql/__generated__";

export const GET_TARGETS_DATA = gql(/* GraphQl */`
query GetTargetsWithOffset(
$label: String,
$offset: Int,
$limit: Int,
$sortBy: String,
$direction: String) {
getTargetsWithOffset(
label: $label
offset: $offset
limit: $limit
sortBy: $sortBy
direction: $direction
) {
total
result {
label
sum
min
max
avg
count
passRate
}
}
}
`);

export const FIND_TARGETS = gql(/* GraphQL */ `
query FindTargets(
$first: Int!
$where: TargetPairWhereInput
$orderBy: TargetPairOrder
$after: Cursor
){
findTargets (first: $first, where: $where, orderBy: $orderBy, after: $after){
totalCount
pageInfo{
startCursor
endCursor
hasNextPage
hasPreviousPage
}
edges {
node {
id
durationInMs
label
success
bazelInvocation {
invocationID
}
}
}
}
}
`);

export default GET_TARGETS_DATA;
26 changes: 26 additions & 0 deletions frontend/src/app/targets/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
'use client';

import React from 'react';
import Content from '@/components/Content';
import PortalCard from '@/components/PortalCard';
import { Space } from 'antd';
import { DeploymentUnitOutlined } from '@ant-design/icons';
import TargetGrid from '@/components/Targets/TargetGrid';

const Page: React.FC = () => {
return (
<Content
content={
<Space direction="vertical" size="middle" style={{ display: 'flex' }}>
<PortalCard
icon={<DeploymentUnitOutlined />}
titleBits={[<span key="title">Targets Overview</span>]}>
<TargetGrid />
</PortalCard>
</Space >
}
/>
);
}

export default Page;
2 changes: 1 addition & 1 deletion frontend/src/components/ActionDataMetrics/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ const ActionDataMetrics: React.FC<{ acMetrics: ActionSummary | undefined; }> = (
</PortalCard> */}
</Col>
<Col span="10">
<PortalCard type="inner" icon={<PieChartOutlined />} titleBits={["User Time Breakdown"]}>
<PortalCard type="inner" icon={<PieChartOutlined />} titleBits={["User Time Breakdown"]} hidden={totalUserTime == 0}>
<PieChart width={600} height={556}>
<Pie
activeIndex={activeIndexRunner}
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/components/AppBar/AppBarMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ import React from 'react';
import { Menu } from 'antd';
import { MenuMode } from 'rc-menu/es/interface';
import { usePathname } from 'next/navigation';
import { ItemType } from 'antd/lib/menu/hooks/useItems';
//import { ItemType } from 'antd/lib/menu/hooks/useItems';
import styles from './index.module.css';
import { getClosestKey } from '@/components/Utilities/navigation';
import { ItemType } from 'antd/lib/menu/interface';

type Props = {
mode: MenuMode;
Expand Down
1 change: 1 addition & 0 deletions frontend/src/components/AppBar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const APP_BAR_MENU_ITEMS: ItemType[] = [
getItem({ depth: 0, href: '/bazel-invocations', title: 'Invocations' }),
getItem({ depth: 0, href: '/trends', title: "Trends" }),
getItem({ depth: 0, href: '/tests', title: "Tests" }),
getItem({ depth: 0, href: '/targets', title: "Targets" }),
];

type Props = {
Expand Down
Loading
Loading