mirror of
https://github.com/eyaltoledano/claude-task-master.git
synced 2026-01-30 06:12:05 +00:00
feat: sort briefs by updated at (#1409)
This commit is contained in:
@@ -3,12 +3,13 @@
|
|||||||
* Reusable functions for selecting briefs interactively or via URL/ID
|
* Reusable functions for selecting briefs interactively or via URL/ID
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import chalk from 'chalk';
|
|
||||||
import search from '@inquirer/search';
|
import search from '@inquirer/search';
|
||||||
import ora, { Ora } from 'ora';
|
import type { AuthManager } from '@tm/core';
|
||||||
import { AuthManager } from '@tm/core';
|
import { formatRelativeTime } from '@tm/core';
|
||||||
import * as ui from './ui.js';
|
import chalk from 'chalk';
|
||||||
|
import ora, { type Ora } from 'ora';
|
||||||
import { getBriefStatusWithColor } from '../ui/formatters/status-formatters.js';
|
import { getBriefStatusWithColor } from '../ui/formatters/status-formatters.js';
|
||||||
|
import * as ui from './ui.js';
|
||||||
|
|
||||||
export interface BriefSelectionResult {
|
export interface BriefSelectionResult {
|
||||||
success: boolean;
|
success: boolean;
|
||||||
@@ -122,8 +123,12 @@ export async function selectBriefInteractive(
|
|||||||
)
|
)
|
||||||
: '';
|
: '';
|
||||||
|
|
||||||
|
const updatedAtDisplay = brief.updatedAt
|
||||||
|
? chalk.gray(` • ${formatRelativeTime(brief.updatedAt)}`)
|
||||||
|
: '';
|
||||||
|
|
||||||
groupedOptions.push({
|
groupedOptions.push({
|
||||||
name: ` ${title}${taskCountDisplay} ${chalk.gray(`(${shortId})`)}`,
|
name: ` ${title}${taskCountDisplay} ${chalk.gray(`(${shortId})`)}${updatedAtDisplay}`,
|
||||||
value: brief,
|
value: brief,
|
||||||
description: description
|
description: description
|
||||||
? chalk.gray(` ${description.slice(0, 80)}`)
|
? chalk.gray(` ${description.slice(0, 80)}`)
|
||||||
@@ -158,8 +163,12 @@ export async function selectBriefInteractive(
|
|||||||
)
|
)
|
||||||
: '';
|
: '';
|
||||||
|
|
||||||
|
const updatedAtDisplay = brief.updatedAt
|
||||||
|
? chalk.gray(` • ${formatRelativeTime(brief.updatedAt)}`)
|
||||||
|
: '';
|
||||||
|
|
||||||
groupedOptions.push({
|
groupedOptions.push({
|
||||||
name: ` ${title}${taskCountDisplay} ${chalk.gray(`(${shortId})`)}`,
|
name: ` ${title}${taskCountDisplay} ${chalk.gray(`(${shortId})`)}${updatedAtDisplay}`,
|
||||||
value: brief,
|
value: brief,
|
||||||
description: description
|
description: description
|
||||||
? chalk.gray(` ${description.slice(0, 80)}`)
|
? chalk.gray(` ${description.slice(0, 80)}`)
|
||||||
|
|||||||
12
package-lock.json
generated
12
package-lock.json
generated
@@ -45,6 +45,7 @@
|
|||||||
"cli-table3": "^0.6.5",
|
"cli-table3": "^0.6.5",
|
||||||
"commander": "^12.1.0",
|
"commander": "^12.1.0",
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
|
"date-fns": "^4.1.0",
|
||||||
"dotenv": "^16.6.1",
|
"dotenv": "^16.6.1",
|
||||||
"express": "^4.21.2",
|
"express": "^4.21.2",
|
||||||
"fastmcp": "^3.23.0",
|
"fastmcp": "^3.23.0",
|
||||||
@@ -13239,6 +13240,16 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "BSD-3-Clause"
|
"license": "BSD-3-Clause"
|
||||||
},
|
},
|
||||||
|
"node_modules/date-fns": {
|
||||||
|
"version": "4.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz",
|
||||||
|
"integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/kossnocorp"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/debug": {
|
"node_modules/debug": {
|
||||||
"version": "2.6.9",
|
"version": "2.6.9",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -28729,6 +28740,7 @@
|
|||||||
"name": "@tm/core",
|
"name": "@tm/core",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@supabase/supabase-js": "^2.57.4",
|
"@supabase/supabase-js": "^2.57.4",
|
||||||
|
"date-fns": "^4.1.0",
|
||||||
"fs-extra": "^11.3.2",
|
"fs-extra": "^11.3.2",
|
||||||
"simple-git": "^3.28.0",
|
"simple-git": "^3.28.0",
|
||||||
"steno": "^4.0.2",
|
"steno": "^4.0.2",
|
||||||
|
|||||||
@@ -83,6 +83,7 @@
|
|||||||
"cli-table3": "^0.6.5",
|
"cli-table3": "^0.6.5",
|
||||||
"commander": "^12.1.0",
|
"commander": "^12.1.0",
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
|
"date-fns": "^4.1.0",
|
||||||
"dotenv": "^16.6.1",
|
"dotenv": "^16.6.1",
|
||||||
"express": "^4.21.2",
|
"express": "^4.21.2",
|
||||||
"fastmcp": "^3.23.0",
|
"fastmcp": "^3.23.0",
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@supabase/supabase-js": "^2.57.4",
|
"@supabase/supabase-js": "^2.57.4",
|
||||||
|
"date-fns": "^4.1.0",
|
||||||
"fs-extra": "^11.3.2",
|
"fs-extra": "^11.3.2",
|
||||||
"simple-git": "^3.28.0",
|
"simple-git": "^3.28.0",
|
||||||
"steno": "^4.0.2",
|
"steno": "^4.0.2",
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ export * from './common/errors/index.js';
|
|||||||
|
|
||||||
// Utils
|
// Utils
|
||||||
export * from './common/utils/index.js';
|
export * from './common/utils/index.js';
|
||||||
|
export * from './utils/time.utils.js';
|
||||||
|
|
||||||
// ========== Domain-Specific Type Exports ==========
|
// ========== Domain-Specific Type Exports ==========
|
||||||
|
|
||||||
|
|||||||
@@ -3,13 +3,13 @@
|
|||||||
* Handles fetching and managing organizations and briefs from the API
|
* Handles fetching and managing organizations and briefs from the API
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { SupabaseClient } from '@supabase/supabase-js';
|
import type { SupabaseClient } from '@supabase/supabase-js';
|
||||||
import {
|
import {
|
||||||
ERROR_CODES,
|
ERROR_CODES,
|
||||||
TaskMasterError
|
TaskMasterError
|
||||||
} from '../../../common/errors/task-master-error.js';
|
} from '../../../common/errors/task-master-error.js';
|
||||||
import { getLogger } from '../../../common/logger/index.js';
|
import { getLogger } from '../../../common/logger/index.js';
|
||||||
import { Database } from '../../../common/types/database.types.js';
|
import type { Database } from '../../../common/types/database.types.js';
|
||||||
import type { Brief } from '../../briefs/types.js';
|
import type { Brief } from '../../briefs/types.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -171,7 +171,8 @@ export class OrganizationService {
|
|||||||
title
|
title
|
||||||
)
|
)
|
||||||
`)
|
`)
|
||||||
.eq('account_id', orgId);
|
.eq('account_id', orgId)
|
||||||
|
.order('updated_at', { ascending: false });
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
throw new TaskMasterError(
|
throw new TaskMasterError(
|
||||||
|
|||||||
18
packages/tm-core/src/utils/time.utils.ts
Normal file
18
packages/tm-core/src/utils/time.utils.ts
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
/**
|
||||||
|
* @fileoverview Time utilities for formatting relative timestamps
|
||||||
|
* Shared across CLI, MCP, extension, and other interfaces
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { formatDistanceToNow } from 'date-fns';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format a date as relative time from now (e.g., "2 hours ago", "3 days ago")
|
||||||
|
* @param date - Date string or Date object to format
|
||||||
|
* @returns Relative time string (e.g., "less than a minute ago", "5 minutes ago", "2 weeks ago")
|
||||||
|
*/
|
||||||
|
export function formatRelativeTime(date: string | Date): string {
|
||||||
|
const dateObj = typeof date === 'string' ? new Date(date) : date;
|
||||||
|
|
||||||
|
// Use date-fns for robust formatting with proper edge case handling
|
||||||
|
return formatDistanceToNow(dateObj, { addSuffix: true });
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user