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

fix(INTERNAL-1384): linking jira tasks #3114

Merged
merged 1 commit into from
Dec 4, 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
6 changes: 3 additions & 3 deletions generated/kysely/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,9 @@ export type ExternalTask = {
stateColor: string | null;
stateCategoryId: number;
stateCategoryName: string;
ownerEmail: string;
ownerName: string;
ownerId: string;
ownerEmail: string | null;
ownerName: string | null;
ownerId: string | null;
creatorEmail: string | null;
creatorName: string | null;
creatorId: string | null;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
-- AlterTable
ALTER TABLE "ExternalTask" ALTER COLUMN "ownerEmail" DROP NOT NULL,
ALTER COLUMN "ownerName" DROP NOT NULL,
ALTER COLUMN "ownerId" DROP NOT NULL;
6 changes: 3 additions & 3 deletions prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -442,9 +442,9 @@ model ExternalTask {
stateColor String?
stateCategoryId Int
stateCategoryName String
ownerEmail String
ownerName String
ownerId String
ownerEmail String?
ownerName String?
ownerId String?
creatorEmail String?
creatorName String?
creatorId String?
Expand Down
19 changes: 16 additions & 3 deletions src/components/CriteriaForm/CriteriaForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ type SuggestItem =
id: string;
title: string;
type: TaskTypeProps;
key: string;
taskKey: string;
};

interface ValidityData {
Expand Down Expand Up @@ -102,7 +102,7 @@ function patchZodSchema<T extends FormValues>(
mode: z.literal('task'),
id: z.string(),
selected: z.object({
key: z.string(),
taskKey: z.string(),
}),
}),
])
Expand Down Expand Up @@ -414,6 +414,14 @@ export const CriteriaForm = ({
return !!(title && selected?.id);
}, [mode, title, selected?.id]);

const disbaleSubmitBtn = useMemo(() => {
if (mode === 'simple') {
return !title.length;
}

return selected == null || selected.title?.length === 0;
}, [mode, title, selected]);

const resetHandler = useCallback(() => {
if (!isEditMode) {
setShowWeightInput(false);
Expand Down Expand Up @@ -513,7 +521,12 @@ export const CriteriaForm = ({

<div className={s.FormControlButtons}>
<Button type="reset" text={tr('Reset')} view="default" />
<Button type="submit" text={isEditMode ? tr('Save') : tr('Add')} view="primary" />
<Button
type="submit"
disabled={disbaleSubmitBtn}
text={isEditMode ? tr('Save') : tr('Add')}
view="primary"
/>
</div>
</div>
</>
Expand Down
12 changes: 6 additions & 6 deletions src/components/GoalActivityFeed/GoalActivityFeed.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ export const GoalActivityFeed = forwardRef<HTMLDivElement, GoalActivityFeedProps
async (data: {
title: string;
weight: string;
selected?: { id?: string; key?: string };
selected?: { id?: string; taskKey?: string };
mode: AddCriteriaMode;
}) => {
await onGoalCriteriaAdd({
Expand All @@ -104,9 +104,9 @@ export const GoalActivityFeed = forwardRef<HTMLDivElement, GoalActivityFeedProps
}
: undefined,
externalTask:
data.mode === 'task' && data.selected?.key
data.mode === 'task' && data.selected?.taskKey
? {
externalKey: data.selected.key,
taskKey: data.selected.taskKey,
}
: undefined,
});
Expand All @@ -119,7 +119,7 @@ export const GoalActivityFeed = forwardRef<HTMLDivElement, GoalActivityFeedProps
id?: string;
title: string;
weight?: number;
selected?: { id?: string; externalKey?: string };
selected?: { id?: string; taskKey?: string };
mode: AddCriteriaMode;
}) => {
if (!data.id) return;
Expand All @@ -136,9 +136,9 @@ export const GoalActivityFeed = forwardRef<HTMLDivElement, GoalActivityFeedProps
}
: undefined,
externalTask:
data.mode === 'task' && data.selected?.externalKey
data.mode === 'task' && data.selected?.taskKey
? {
externalKey: data.selected.externalKey,
taskKey: data.selected.taskKey,
}
: undefined,
});
Expand Down
1 change: 1 addition & 0 deletions src/components/GoalCriteria/GoalCriteria.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

.GoalCriteriaWeightColumn {
text-align: right;
justify-content: flex-end;
}

.GoalCriteriaTableRow {
Expand Down
13 changes: 8 additions & 5 deletions src/components/GoalCriteria/GoalCriteria.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ interface ExternalTaskCriteriaProps extends CriteriaProps {
id: string;
title: string;
externalKey: string;
taskKey: string;
project: string;
type: ExternalTaskTypeProps;
state?: {
Expand Down Expand Up @@ -155,6 +156,7 @@ export function mapCriteria<
id: criteria.id,
externalTask: {
...task,
taskKey: task.externalKey,
project: task.projectId,
type: {
src: task.typeIconUrl,
Expand Down Expand Up @@ -190,7 +192,7 @@ const SimpleCriteria: React.FC<Omit<CriteriaProps, 'id'> & OnCheckCriteriaCallba
onCheck,
}) => (
<TableRow className={classes.GoalCriteriaTableRow}>
<TableCell width={350}>
<TableCell width={450}>
<Checkbox
className={classNames(classes.GoalCriteriaItemCheckbox, {
[classes.CriteriaIsDone]: isDone,
Expand Down Expand Up @@ -231,9 +233,10 @@ const ExternalTaskCriteria = ({ title, externalTask, weight, isDone }: Omit<Exte

return (
<>
<TableCell className={classes.GoalCriteriaTitleCell} width={200}>
<TableCell className={classes.GoalCriteriaTitleCell} width={300}>
<JiraTaskBadge
title={title}
taskKey={externalTask.externalKey}
state={
externalTask.state
? {
Expand Down Expand Up @@ -282,7 +285,7 @@ const GoalCriteria = ({ title, goal, weight, isDone }: Omit<GoalCriteriaProps, '

return (
<>
<TableCell className={classes.GoalCriteriaTitleCell} width={200}>
<TableCell className={classes.GoalCriteriaTitleCell} width={300}>
<GoalBadge
title={title}
state={getStateProps(goal.state)}
Expand Down Expand Up @@ -461,7 +464,7 @@ export const Criteria: React.FC<
id: props.externalTask.id,
title: props.externalTask.title,
type: props.externalTask.type,
key: props.externalTask.externalKey,
taskKey: props.externalTask.externalKey,
itemType: 'task',
},
},
Expand Down Expand Up @@ -501,7 +504,7 @@ export const Criteria: React.FC<
valuesToUpdate.selected.id = values.selected.id;
break;
case 'task':
valuesToUpdate.selected.externalKey = values.selected.key;
valuesToUpdate.selected.externalKey = values.selected.taskKey;
break;
default:
}
Expand Down
3 changes: 2 additions & 1 deletion src/components/GoalCriteriaSuggest.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ interface Goal {
interface Task {
id: string;
title: string;
taskKey: string;
type?: Record<string, unknown> | null;
state?: Record<string, unknown> | null;
project: string;
Expand Down Expand Up @@ -115,7 +116,7 @@ export const GoalCriteriaSuggest: React.FC<GoalCriteriaSuggestProps> = ({

return issues.map((issue) => ({
...issue,
key: issue.externalKey,
taskKey: issue.externalKey,
state: null,
id: issue.externalId,
title: issue.title,
Expand Down
1 change: 1 addition & 0 deletions src/components/HistoryRecord/HistoryRecord.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,7 @@ const HistoryRecordCriteriaItem: React.FC<CriteriaItem> = ({ criteriaGoal, exter
title: externalTask.state,
color: externalTask.stateColor,
}}
taskKey={externalTask.externalKey}
title={externalTask.title}
href={routes.jiraTask(externalTask.externalKey)}
strike={strike}
Expand Down
5 changes: 0 additions & 5 deletions src/components/JiraTaskBadge/JiraTaskBadge.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,6 @@
font-size: 16px;
}

.JiraTaskBadgeProjectName {
/* must be used of current font-size, but not root font-size */
margin-left: 0.25em;
}

.JiraTaskBadgeState {
color: white;
background-color: var(--task-badge-color, var(--gray-500));
Expand Down
18 changes: 9 additions & 9 deletions src/components/JiraTaskBadge/JiraTaskBadge.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { NextLink } from '../NextLink';
import styles from './JiraTaskBadge.module.css';

interface JiraTaskBadgeProps extends Omit<React.HTMLAttributes<HTMLSpanElement>, 'color' | 'title'> {
taskKey: string;
title: React.ReactNode;
href?: string;
type?: {
Expand Down Expand Up @@ -55,15 +56,14 @@ export const JiraTaskBadgeState: React.FC<{ state: string; color?: string | null
);
};

const JiraTaskBadgeLabel: React.FC<Pick<JiraTaskBadgeProps, 'title' | 'project'>> = ({ title, project }) => {
const JiraTaskBadgeLabel: React.FC<Pick<JiraTaskBadgeProps, 'title' | 'taskKey'>> = ({ title, taskKey }) => {
return (
<>
{title}
{nullable(project, (p) => (
<Text className={styles.JiraTaskBadgeProjectName} as="span" color="var(--gray-500)">
({p})
</Text>
))}
{String.fromCharCode(0x0d)}
<Text as="span" color="var(--gray-500)">
({taskKey})
</Text>
</>
);
};
Expand All @@ -76,7 +76,7 @@ export const JiraTaskBadge: React.FC<JiraTaskBadgeProps> = ({
onClick,
type,
state,
project,
taskKey,
...attrs
}) => {
return (
Expand All @@ -94,10 +94,10 @@ export const JiraTaskBadge: React.FC<JiraTaskBadgeProps> = ({
href,
(h) => (
<NextLink href={h} target="_blank" view="secondary" onClick={onClick}>
<JiraTaskBadgeLabel title={title} project={project} />
<JiraTaskBadgeLabel title={title} taskKey={taskKey} />
</NextLink>
),
<JiraTaskBadgeLabel title={title} project={project} />,
<JiraTaskBadgeLabel title={title} taskKey={taskKey} />,
)}
action="dynamic"
{...attrs}
Expand Down
2 changes: 1 addition & 1 deletion src/schema/criteria.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export const criteriaSchema = z.object({
.optional(),
externalTask: z
.object({
externalKey: z.string(),
taskKey: z.string(),
})
.optional(),
});
Expand Down
4 changes: 2 additions & 2 deletions src/utils/integration/jira.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,9 @@ export interface JiraIssue {
self: string;
summary: string;
description: string;
creator: JiraUser;
creator: JiraUser | null;
assignee: JiraUser | null;
reporter: JiraUser;
reporter: JiraUser | null;
status: JiraIssueStatus;
project: JiraProject;
priority: JiraProject;
Expand Down
12 changes: 6 additions & 6 deletions src/utils/worker/externalTasksJob.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,12 @@ const createSQLValues = (sources: JiraIssue[]) =>
issuetype.name,
issuetype.iconUrl,
issuetype.id,
reporter.emailAddress,
reporter.key,
reporter.displayName || reporter.name || null,
creator.emailAddress,
creator.key,
creator.displayName || creator.name || null,
reporter?.emailAddress,
reporter?.key,
reporter?.displayName || reporter?.name || null,
creator?.emailAddress,
creator?.key,
creator?.displayName || creator?.name || null,
assignee?.emailAddress,
assignee?.key,
assignee?.displayName || assignee?.name || null,
Expand Down
16 changes: 9 additions & 7 deletions trpc/queries/external.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { searchIssue } from '../../src/utils/integration/jira';
import { JiraUser, searchIssue } from '../../src/utils/integration/jira';
import { db } from '../connection/kysely';
import { ExternalTask } from '../../generated/kysely/types';
import { ExtractTypeFromGenerated } from '../utils';
Expand Down Expand Up @@ -43,6 +43,8 @@ export const getOrCreateExternalTask = async ({ id }: { id: string }) => {
resolution,
} = externalIssue;

const creatorOrReporter = [reporter, creator].find((val) => val != null) || ({} as JiraUser);

return insertExternalTask({
title,
externalId,
Expand All @@ -58,12 +60,12 @@ export const getOrCreateExternalTask = async ({ id }: { id: string }) => {
stateCategoryName: state.statusCategory.name,
project: project.name,
projectId: project.key,
ownerName: reporter.displayName,
ownerEmail: reporter.emailAddress,
ownerId: reporter.key,
creatorName: creator.displayName,
creatorEmail: creator.emailAddress,
creatorId: creator.key,
ownerName: creatorOrReporter.displayName ?? creatorOrReporter.name,
ownerEmail: creatorOrReporter.emailAddress,
ownerId: creatorOrReporter.key,
creatorName: creatorOrReporter.displayName ?? creatorOrReporter.name,
creatorEmail: creatorOrReporter.emailAddress,
creatorId: creatorOrReporter.key,
assigneeName: assignee?.displayName ?? null,
assigneeEmail: assignee?.emailAddress ?? null,
assigneeId: assignee?.key ?? null,
Expand Down
Loading
Loading