Skip to content
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
21 changes: 14 additions & 7 deletions src/components/ui/MyWorkRow.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ describe('MyWorkRow', () => {
expect(queryByTestId('chapter-conflict-indicator')).toBeNull();
});

it('renders indicators in the shared cloud, conflict, ownership order', () => {
const { getAllByTestId } = render(
it('shows only the conflict indicator when both conflict and ownership apply', () => {
const { getAllByTestId, queryByTestId } = render(
<MyWorkRow
chapter={{ ...baseChapter, hasConflict: true }}
onPress={jest.fn()}
Expand All @@ -85,10 +85,17 @@ describe('MyWorkRow', () => {

expect(
getAllByTestId(/-indicator$/).map(node => node.props.testID),
).toEqual([
'chapter-cloud-sync-indicator',
'chapter-conflict-indicator',
'chapter-ownership-indicator',
]);
).toEqual(['chapter-cloud-sync-indicator', 'chapter-conflict-indicator']);
expect(queryByTestId('chapter-ownership-indicator')).toBeNull();
});

it('shows the ownership indicator when there is no conflict', () => {
const { getAllByTestId } = render(
<MyWorkRow chapter={baseChapter} onPress={jest.fn()} />,
);

expect(
getAllByTestId(/-indicator$/).map(node => node.props.testID),
).toEqual(['chapter-cloud-sync-indicator', 'chapter-ownership-indicator']);
});
});
9 changes: 7 additions & 2 deletions src/components/ui/MyWorkRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,13 @@ export function MyWorkRow({
{display.showCloudSync ? (
<ChapterCloudSyncIndicator syncState={chapter.syncState} />
) : null}
{chapter.hasConflict ? <ChapterConflictIndicator /> : null}
<ChapterOwnershipIndicator ownershipState={chapter.ownershipState} />
{chapter.hasConflict ? (
<ChapterConflictIndicator />
) : (
<ChapterOwnershipIndicator
ownershipState={chapter.ownershipState}
/>
)}
</View>

<View style={styles.metaRow}>
Expand Down
21 changes: 14 additions & 7 deletions src/components/ui/ProjectChapterRow.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ describe('ProjectChapterRow', () => {
expect(queryByTestId('chapter-conflict-indicator')).toBeNull();
});

it('renders indicators in the shared cloud, conflict, ownership order', () => {
const { getAllByTestId } = render(
it('shows only the conflict indicator when both conflict and ownership apply', () => {
const { getAllByTestId, queryByTestId } = render(
<ProjectChapterRow
chapter={{ ...baseChapter, hasConflict: true }}
onPress={jest.fn()}
Expand All @@ -85,10 +85,17 @@ describe('ProjectChapterRow', () => {

expect(
getAllByTestId(/-indicator$/).map(node => node.props.testID),
).toEqual([
'chapter-cloud-sync-indicator',
'chapter-conflict-indicator',
'chapter-ownership-indicator',
]);
).toEqual(['chapter-cloud-sync-indicator', 'chapter-conflict-indicator']);
expect(queryByTestId('chapter-ownership-indicator')).toBeNull();
});

it('shows the ownership indicator when there is no conflict', () => {
const { getAllByTestId } = render(
<ProjectChapterRow chapter={baseChapter} onPress={jest.fn()} />,
);

expect(
getAllByTestId(/-indicator$/).map(node => node.props.testID),
).toEqual(['chapter-cloud-sync-indicator', 'chapter-ownership-indicator']);
});
});
11 changes: 6 additions & 5 deletions src/components/ui/ProjectChapterRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,12 @@ export function ProjectChapterRow({
) : null}
{chapter.hasConflict ? (
<ChapterConflictIndicator size={iconSizes.projectSync} />
) : null}
<ChapterOwnershipIndicator
ownershipState={chapter.ownershipState}
size={iconSizes.projectSync}
/>
) : (
<ChapterOwnershipIndicator
ownershipState={chapter.ownershipState}
size={iconSizes.projectSync}
/>
)}
</View>

<View style={styles.metaRow}>
Expand Down
15 changes: 13 additions & 2 deletions src/db/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@ import {
MY_WORK_CHAPTER_WHERE,
} from '../utils/myWorkChapterFilter';
import { getBadgeStage, getWorkflowStage } from '../utils/workflowStage';
import { deriveChapterOwnershipState } from '../utils/chapterOwnershipState';
import {
deriveChapterOwnershipState,
resolveStageAssigneeId,
} from '../utils/chapterOwnershipState';

function parseConnectivityProfile(
metadata: string | null,
Expand Down Expand Up @@ -450,6 +453,7 @@ function mapChapterRowCore(
| 'id'
| 'book_name'
| 'chapter_number'
| 'status'
| 'updated_at'
| 'submitted_time'
| 'last_recording_activity'
Expand All @@ -459,6 +463,7 @@ function mapChapterRowCore(
| 'completed_verses'
| 'downloaded_verses'
| 'assigned_user_id'
| 'peer_checker_id'
| 'has_conflict'
>,
currentUserId: number,
Expand All @@ -474,7 +479,11 @@ function mapChapterRowCore(
chapterNumber: row.chapter_number,
syncState: deriveChapterSyncState(recordingCount, pendingCount),
ownershipState: deriveChapterOwnershipState(
row.assigned_user_id,
resolveStageAssigneeId(
row.status,
row.assigned_user_id,
row.peer_checker_id,
),
currentUserId,
),
lastActivityAt: activity.lastActivityAt,
Expand Down Expand Up @@ -523,6 +532,7 @@ export async function getProjectChapters(
ca.updated_at,
ca.submitted_time,
ca.assigned_user_id,
ca.peer_checker_id,
b.eng_display_name AS book_name,
${RECORDING_AGGREGATES},
(
Expand Down Expand Up @@ -571,6 +581,7 @@ export async function getMyWorkChapters(
ca.updated_at,
ca.submitted_time,
ca.assigned_user_id,
ca.peer_checker_id,
b.eng_display_name AS book_name,
p.name AS project_name,
tl.lang_name AS target_language_name,
Expand Down
2 changes: 2 additions & 0 deletions src/types/db/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ export interface ProjectChapterRow {
completed_verses: number;
downloaded_verses: number;
assigned_user_id?: number | null;
peer_checker_id?: number | null;
has_conflict: number;
}

Expand All @@ -110,6 +111,7 @@ export interface MyWorkChapterRow {
completed_verses: number;
downloaded_verses: number;
assigned_user_id?: number | null;
peer_checker_id?: number | null;
has_conflict: number;
}

Expand Down
36 changes: 35 additions & 1 deletion src/utils/chapterOwnershipState.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { deriveChapterOwnershipState } from './chapterOwnershipState';
import {
deriveChapterOwnershipState,
resolveStageAssigneeId,
} from './chapterOwnershipState';

describe('deriveChapterOwnershipState', () => {
it('returns unassigned when there is no assigned user', () => {
Expand All @@ -15,3 +18,34 @@ describe('deriveChapterOwnershipState', () => {
expect(deriveChapterOwnershipState(42, null)).toBe('other');
});
});

describe('resolveStageAssigneeId', () => {
it('returns the drafter at Drafting (draft or not_started)', () => {
expect(resolveStageAssigneeId('draft', 42, 99)).toBe(42);
expect(resolveStageAssigneeId('not_started', 42, 99)).toBe(42);
});

it('returns null at Drafting when no drafter is assigned', () => {
expect(resolveStageAssigneeId('not_started', null, 99)).toBeNull();
});

it('returns the PM-assigned peer checker at Peer Check', () => {
expect(resolveStageAssigneeId('peer_check', 42, 99)).toBe(99);
});

it('returns null/undefined at Peer Check when open/unassigned (#442)', () => {
expect(resolveStageAssigneeId('peer_check', 42, null)).toBeNull();
expect(resolveStageAssigneeId('peer_check', 42, undefined)).toBeUndefined();
});

it('returns null for stages with no assignee concept', () => {
expect(resolveStageAssigneeId('community_review', 42, 99)).toBeNull();
expect(resolveStageAssigneeId('consultant_check', 42, 99)).toBeNull();
expect(resolveStageAssigneeId('complete', 42, 99)).toBeNull();
});

it('returns null for unrecognized or null status', () => {
expect(resolveStageAssigneeId('some_future_status', 42, 99)).toBeNull();
expect(resolveStageAssigneeId(null, 42, 99)).toBeNull();
});
});
18 changes: 18 additions & 0 deletions src/utils/chapterOwnershipState.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { getWorkflowStage } from './workflowStage';
import { ChapterOwnershipState } from '../types/db/types';

export function deriveChapterOwnershipState(
Expand All @@ -9,3 +10,20 @@ export function deriveChapterOwnershipState(
if (currentUserId !== null && assignedUserId === currentUserId) return 'mine';
return 'other';
}

export function resolveStageAssigneeId(
status: string | null | undefined,
assignedUserId: number | null | undefined,
peerCheckerId: number | null | undefined,
): number | null | undefined {
const stage = getWorkflowStage(status);
switch (stage) {
case 'draft':
case 'not_started':
return assignedUserId;
case 'peer_check':
return peerCheckerId;
default:
return null;
}
}
Loading