Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
017244a
feat(OUT-2763): new tab design
arpandhakal Dec 23, 2025
8f1d0a8
fix(OUT-2763): fixed height
arpandhakal Dec 23, 2025
d4079f4
feat(OUT-2761): redesigned cards
arpandhakal Dec 23, 2025
f08d4f2
fix(OUT-2762): showed assignee name on hover instead of "change assig…
arpandhakal Dec 24, 2025
f6a8ff7
fix(OUT-2761): applied colors from theme on workflowState color and o…
arpandhakal Dec 24, 2025
da8a3df
fix(OUT-2763): everything
arpandhakal Dec 24, 2025
4606b32
fix(OUT-2763): searchbar and display selector div height issue in sma…
arpandhakal Dec 24, 2025
23d1765
fix(OUT-2763): applied requested changes
arpandhakal Dec 25, 2025
e74c91b
fix(OUT-2876): visual improvements
arpandhakal Jan 7, 2026
909d99c
fix(OUT-2904): heavily optimized tasks list virtualization to remove …
arpandhakal Jan 9, 2026
cda227c
fix(OUT-2904): drop item fixed
arpandhakal Jan 9, 2026
9670e72
fix(OUT-2656): supported adding viewers to subtask creation in CRM de…
arpandhakal Dec 19, 2025
db7fe03
fix(OUT-2926): templates dropdown width increase.
arpandhakal Jan 14, 2026
7551835
fix(OUT-2926): comment added
arpandhakal Jan 14, 2026
afc9d0f
fix(OUT-2831): removed subTaskTemplates object from subTaskTemplates …
arpandhakal Jan 13, 2026
dd4a49e
fix(OUT-2831): applied requested changes
arpandhakal Jan 14, 2026
983d8c1
chore: prep for Next.js 16 upgrade
arpandhakal Dec 29, 2025
664262a
feat(OUT-2844): upgrade next version to 16
arpandhakal Dec 30, 2025
4f585d6
feat(OUT-2844): upgrade next version to 16
arpandhakal Dec 30, 2025
884b59e
feat(OUT-2844): upgrade next version to 16
arpandhakal Dec 30, 2025
da90529
feat(OUT-2844): upgrade next version to 16
arpandhakal Dec 30, 2025
5c4f0cf
fix(OUT-2844): stylish js text-table dependency issue
arpandhakal Dec 30, 2025
9839b39
feat(OUT-2844): upgrade next version to 16
arpandhakal Dec 30, 2025
cfdd3ad
feat(OUT-2844): upgrade next version to 16
arpandhakal Dec 30, 2025
c318668
feat(OUT-2844): upgrade next version to 16
arpandhakal Dec 30, 2025
3831677
fix(OUT-2844): added text-table as dev dependency to fix linting issu…
arpandhakal Dec 30, 2025
d339ca1
fix(OUT-2844): added react-hooks/static-components rule and fixed rel…
arpandhakal Dec 30, 2025
cfc7c6f
fix(OUT-2844): reverted turning off reactCompiler in next config
arpandhakal Dec 31, 2025
eefbe18
fix(OUT-2844): fixed nested link tags, caching and removed customScro…
arpandhakal Jan 12, 2026
d9d599a
fix(OUT-2848): refactored tempalte realtime pattern.
arpandhakal Jan 5, 2026
87af420
fix(OUT-2847): seggregate task service for public and web
arpandhakal Jan 6, 2026
a87dcb9
fix(OUT-2847): refactored createSubtasksFromTemplate to be resuable f…
arpandhakal Jan 7, 2026
d863c7c
fix(OUT-2847): file naming convention followed and changed access sco…
arpandhakal Jan 12, 2026
f70031b
fix(OUT-2911): sidebar skeleton layout fixed
arpandhakal Jan 13, 2026
0fcd724
feat(OUT-2929): disable sending errors to sentry from preview apps
arpandhakal Jan 14, 2026
7fa117b
fix(OUT-2929): cleanup
arpandhakal Jan 14, 2026
fb66a6d
fix(OUT-2929): enabled transaction events for preview app in sentry c…
arpandhakal Jan 14, 2026
2c8346f
tryfix: only suppress error type telemetry
rrojan Jan 14, 2026
a41d6d5
tryfix: only suppress error type telemetry
rrojan Jan 14, 2026
4d0259b
tryfix: only suppress error type telemetry
rrojan Jan 14, 2026
3539648
fix(OUT-2937): manage template button missing.
arpandhakal Jan 16, 2026
d85dc02
fix(out-2943): fix alignment of search and filter icons (#1095)
priosshrsth Jan 19, 2026
eb21501
fix(OUT-2944): enabled feature flag to retry assembly api calls on 40…
arpandhakal Jan 19, 2026
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
3 changes: 0 additions & 3 deletions .eslintrc.json

This file was deleted.

19 changes: 19 additions & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { defineConfig } from 'eslint/config'
import nextCoreWebVitals from 'eslint-config-next/core-web-vitals'
import path from 'node:path'
import { fileURLToPath } from 'node:url'

const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)

export default defineConfig([
{
extends: [...nextCoreWebVitals],
rules: {
'react-hooks/set-state-in-effect': 'off',
'react-hooks/refs': 'off',
'react-hooks/preserve-manual-memoization': 'off',
'react-compiler/react-compiler': 'off',
},
},
])
8 changes: 8 additions & 0 deletions next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@ const nextConfig = {

return config
},
turbopack: {
rules: {
'*.svg': {
loaders: ['@svgr/webpack'],
as: '*.jsx',
},
},
},
}

module.exports = withSentryConfig(nextConfig, {
Expand Down
18 changes: 10 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,26 +29,27 @@
"jsdom": "^25.0.1",
"localforage": "^1.10.0",
"marked": "^16.3.0",
"next": "14.2.35",
"next": "16.1.1",
"nextjs-progressloader": "^1.2.0",
"p-retry": "^6.2.0",
"prisma": "^5.19.0",
"react": "^18",
"react": "19.2.3",
"react-dnd": "^16.0.1",
"react-dnd-html5-backend": "^16.0.1",
"react-dnd-touch-backend": "^16.0.1",
"react-dom": "^18.3",
"react-dom": "19.2.3",
"react-redux": "^9.1.0",
"react-zoom-pan-pinch": "^3.7.0",
"server-only": "^0.0.1",
"supabase": "^2.1.1",
"swr": "^2.2.5",
"tapwrite": "1.1.93",
"tapwrite": "1.1.94",
"uuid": "^11.1.0",
"zod": "^3.23.8"
},
"description": "A comprehensive task management app",
"devDependencies": {
"@eslint/eslintrc": "^3.3.3",
"@faker-js/faker": "^8.4.1",
"@ngrok/ngrok": "^1.4.1",
"@svgr/webpack": "^8.1.0",
Expand All @@ -57,18 +58,19 @@
"@types/jest": "^29.5.12",
"@types/jsdom": "^21.1.7",
"@types/node": "^20",
"@types/react": "^18",
"@types/react": "19.2.7",
"@types/react-custom-scrollbars": "^4.0.13",
"@types/react-dom": "^18",
"@types/react-dom": "19.2.3",
"autoprefixer": "^10.0.1",
"eslint": "^8",
"eslint-config-next": "14.0.4",
"eslint": "^9",
"eslint-config-next": "16.1.1",
"husky": "^8.0.0",
"jest": "^29.7.0",
"nodemon": "^3.1.9",
"open": "^10.1.0",
"prettier": "^3.1.1",
"tailwindcss": "^3.3.0",
"text-table": "^0.2.0",
"tsx": "^4.16.5",
"typescript": "^5"
},
Expand Down
88 changes: 48 additions & 40 deletions sentry.client.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,47 +2,55 @@
// The config you add here will be used whenever a users loads a page in their browser.
// https://docs.sentry.io/platforms/javascript/guides/nextjs/

import * as Sentry from '@sentry/nextjs'
import * as Sentry from "@sentry/nextjs";

const dsn = process.env.NEXT_PUBLIC_SENTRY_DSN || process.env.SENTRY_DSN
const vercelEnv = process.env.NEXT_PUBLIC_VERCEL_ENV
const isProd = process.env.NEXT_PUBLIC_VERCEL_ENV === 'production'
const dsn = process.env.NEXT_PUBLIC_SENTRY_DSN || process.env.SENTRY_DSN;
const vercelEnv = process.env.NEXT_PUBLIC_VERCEL_ENV;
const isProd = process.env.NEXT_PUBLIC_VERCEL_ENV === "production";

if (dsn) {
Sentry.init({
dsn,

// Adjust this value in production, or use tracesSampler for greater control
tracesSampleRate: isProd ? 0.2 : 1,
profilesSampleRate: 0.1,
// NOTE: reducing sample only 10% of transactions in prod to get general trends instead of detailed and overfitted data

// Setting this option to true will print useful information to the console while you're setting up Sentry.
debug: false,

// You can remove this option if you're not planning to use the Sentry Session Replay feature:
// NOTE: Since session replay barely helps us anyways, getting rid of it to reduce some bundle size at least
// replaysOnErrorSampleRate: 1.0,
// replaysSessionSampleRate: 0,
integrations: [
Sentry.browserTracingIntegration(),
// Sentry.replayIntegration({
// Additional Replay configuration goes in here, for example:
// maskAllText: true,
// blockAllMedia: true,
// }),
],

// ignoreErrors: [/fetch failed/i],
ignoreErrors: [/fetch failed/i],

beforeSend(event) {
event.tags = {
...event.tags,
// Adding additional app_env tag for cross-checking
app_env: isProd ? 'production' : vercelEnv || 'development',
}
return event
},
})
Sentry.init({
dsn,

// Adjust this value in production, or use tracesSampler for greater control
tracesSampleRate: isProd ? 0.2 : 1,
profilesSampleRate: 0.1,
// NOTE: reducing sample only 10% of transactions in prod to get general trends instead of detailed and overfitted data

// Setting this option to true will print useful information to the console while you're setting up Sentry.
debug: false,

// You can remove this option if you're not planning to use the Sentry Session Replay feature:
// NOTE: Since session replay barely helps us anyways, getting rid of it to reduce some bundle size at least
// replaysOnErrorSampleRate: 1.0,
// replaysSessionSampleRate: 0,
integrations: [
Sentry.browserTracingIntegration({
beforeStartSpan: (e) => {
console.info("SentryBrowserTracingSpan", e.name);
return e;
},
}),
// Sentry.replayIntegration({
// Additional Replay configuration goes in here, for example:
// maskAllText: true,
// blockAllMedia: true,
// }),
],

// ignoreErrors: [/fetch failed/i],
ignoreErrors: [/fetch failed/i],

beforeSend(event) {
if (!isProd && event.type === undefined) {
return null;
}
event.tags = {
...event.tags,
// Adding additional app_env tag for cross-checking
app_env: isProd ? "production" : vercelEnv || "development",
};
return event;
},
});
}
33 changes: 21 additions & 12 deletions sentry.server.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,31 @@
// The config you add here will be used whenever the server handles a request.
// https://docs.sentry.io/platforms/javascript/guides/nextjs/

import * as Sentry from '@sentry/nextjs'
import * as Sentry from "@sentry/nextjs";

const dsn = process.env.NEXT_PUBLIC_SENTRY_DSN || process.env.SENTRY_DSN
const dsn = process.env.NEXT_PUBLIC_SENTRY_DSN || process.env.SENTRY_DSN;
const vercelEnv = process.env.NEXT_PUBLIC_VERCEL_ENV;
const isProd = process.env.NEXT_PUBLIC_VERCEL_ENV === "production";

if (dsn) {
Sentry.init({
dsn,
Sentry.init({
dsn,

// Adjust this value in production, or use tracesSampler for greater control
tracesSampleRate: 1,
// Adjust this value in production, or use tracesSampler for greater control
tracesSampleRate: 1,

// Setting this option to true will print useful information to the console while you're setting up Sentry.
debug: false,
// Setting this option to true will print useful information to the console while you're setting up Sentry.
debug: false,

// Uncomment the line below to enable Spotlight (https://spotlightjs.com)
// spotlight: process.env.NODE_ENV === 'development',
ignoreErrors: [/fetch failed/i],
})
// Uncomment the line below to enable Spotlight (https://spotlightjs.com)
// spotlight: process.env.NODE_ENV === 'development',
ignoreErrors: [/fetch failed/i],

beforeSend(event) {
if (!isProd && event.type === undefined) {
return null;
}
return event;
},
});
}
7 changes: 3 additions & 4 deletions src/app/(home)/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,10 @@ export async function getViewSettings(token: string): Promise<CreateViewSettings
return resp
}

export default async function Main({
searchParams,
}: {
searchParams: { token: string; taskId?: string } & UrlActionParamsType
export default async function Main(props: {
searchParams: Promise<{ token: string; taskId?: string } & UrlActionParamsType>
}) {
const searchParams = await props.searchParams
const token = searchParams.token

const parsedToken = z.string().safeParse(searchParams.token)
Expand Down
4 changes: 1 addition & 3 deletions src/app/_fetchers/OneTaskDataFetcher.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
}

export const OneTaskDataFetcher = ({ token, task_id, initialTask }: OneTaskDataFetcherProps & PropsWithToken) => {
const hasDispatchedRef = useRef(false)
const buildQueryString = (token: string) => {
const queryParams = new URLSearchParams({ token })

Expand All @@ -30,7 +29,7 @@
})

useEffect(() => {
if (!hasDispatchedRef.current && data?.task) {
if (data?.task) {
//only invalidate cache on mount.
const newTask = structuredClone(data.task)
if (initialTask?.body && newTask.body === undefined) {
Expand All @@ -44,9 +43,8 @@
}
}
store.dispatch(setActiveTask(newTask))
hasDispatchedRef.current = true
}
}, [data])

Check warning on line 47 in src/app/_fetchers/OneTaskDataFetcher.tsx

View workflow job for this annotation

GitHub Actions / Run linters

React Hook useEffect has a missing dependency: 'initialTask'. Either include it or remove the dependency array

Check warning on line 47 in src/app/_fetchers/OneTaskDataFetcher.tsx

View workflow job for this annotation

GitHub Actions / Run linters

React Hook useEffect has a missing dependency: 'initialTask'. Either include it or remove the dependency array

return null
}
6 changes: 5 additions & 1 deletion src/app/api/activity-logs/[id]/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ import { ActivityLogService } from '@api/activity-logs/services/activity-log.ser
import { IdParams } from '@api/core/types/api'
import { unstable_noStore as noStore } from 'next/cache'

export const GET = async (req: NextRequest, { params: { id } }: IdParams) => {
export const GET = async (req: NextRequest, props: IdParams) => {
const params = await props.params

const { id } = params

noStore()
const user = await authenticate(req)

Expand Down
3 changes: 2 additions & 1 deletion src/app/api/attachments/attachments.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ export const getAttachments = async (req: NextRequest) => {
return NextResponse.json({ attachments })
}

export const deleteAttachment = async (req: NextRequest, { params: { id } }: IdParams) => {
export const deleteAttachment = async (req: NextRequest, { params }: IdParams) => {
const { id } = await params
const user = await authenticate(req)
const attachmentsService = new AttachmentsService(user)
await attachmentsService.deleteAttachment(id)
Expand Down
6 changes: 4 additions & 2 deletions src/app/api/comment/comment.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ export const createComment = async (req: NextRequest) => {
return NextResponse.json({ comment }, { status: httpStatus.CREATED })
}

export const deleteComment = async (req: NextRequest, { params: { id } }: IdParams) => {
export const deleteComment = async (req: NextRequest, { params }: IdParams) => {
const { id } = await params
const user = await authenticate(req)

const commentService = new CommentService(user)
Expand All @@ -27,7 +28,8 @@ export const deleteComment = async (req: NextRequest, { params: { id } }: IdPara
return NextResponse.json({ message: 'Comment deleted!' })
}

export const updateComment = async (req: NextRequest, { params: { id } }: IdParams) => {
export const updateComment = async (req: NextRequest, { params }: IdParams) => {
const { id } = await params
const user = await authenticate(req)

const data = UpdateCommentSchema.parse(await req.json())
Expand Down
4 changes: 1 addition & 3 deletions src/app/api/core/types/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,5 @@ export enum Resource {
* NextParam when uuid is being used as a dynamic param (slug) for accessing a resource
*/
export type IdParams = {
params: {
id: string
}
params: Promise<{ id: string }>
}
8 changes: 7 additions & 1 deletion src/app/api/core/utils/withRetry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { StatusableError } from '@/types/CopilotApiError'
import pRetry, { FailedAttemptError } from 'p-retry'
import * as Sentry from '@sentry/nextjs'

export const RETRY_404_ENABLED = process.env.RETRY_404 === 'true'

export const withRetry = async <T>(fn: (...args: any[]) => Promise<T>, args: any[]): Promise<T> => {
let isEventProcessorRegistered = false

Expand Down Expand Up @@ -41,7 +43,11 @@ export const withRetry = async <T>(fn: (...args: any[]) => Promise<T>, args: any
// Typecasting because Copilot doesn't export an error class
const err = error as StatusableError
// Retry if statusCode is 429 (ratelimit), 408 (timeouts), or any server related (5xx) error
return [408, 429].includes(err.status) || (err.status >= 500 && err.status <= 511)
return (
[408, 429].includes(err.status) ||
(err.status >= 500 && err.status <= 511) ||
(RETRY_404_ENABLED && err.status === 404)
)
},
},
)
Expand Down
3 changes: 2 additions & 1 deletion src/app/api/tasks/[id]/activity-logs/activity.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import authenticate from '@api/core/utils/authenticate'
import httpStatus from 'http-status'
import { NextRequest, NextResponse } from 'next/server'

export const get = async (req: NextRequest, { params: { id } }: IdParams) => {
export const get = async (req: NextRequest, { params }: IdParams) => {
const { id } = await params
const user = await authenticate(req)

const { expandComments } = getSearchParams(req.nextUrl.searchParams, ['expandComments'])
Expand Down
Loading
Loading