From f4b77be7825c64ae03b3b4cea190413ecb399704 Mon Sep 17 00:00:00 2001 From: Paul Hovley Date: Fri, 8 Nov 2024 20:56:38 -0700 Subject: [PATCH 1/8] grey text --- packages/app/src/components/Home/Source/SourceTimeChart.tsx | 2 +- packages/server/src/main.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/app/src/components/Home/Source/SourceTimeChart.tsx b/packages/app/src/components/Home/Source/SourceTimeChart.tsx index ddbfcd74..bede495c 100644 --- a/packages/app/src/components/Home/Source/SourceTimeChart.tsx +++ b/packages/app/src/components/Home/Source/SourceTimeChart.tsx @@ -41,7 +41,7 @@ export const SourceTimeChart = ({ /> - + {time} diff --git a/packages/server/src/main.ts b/packages/server/src/main.ts index 3942f966..a4b811c3 100644 --- a/packages/server/src/main.ts +++ b/packages/server/src/main.ts @@ -40,7 +40,7 @@ export const bootstrap = async () => { ] : [ 'https://codeclimbers.io', - 'chrome-extension://fdmoefklpgbjapealpjfailnmalbgpbe', + /chrome-extension.+$/, 'http://localhost:5173', /\.codeclimbers\.io$/, /\.web\.app$/, From 69ecec4c50cb8b8a22d9fbfd1bb4737389818c61 Mon Sep 17 00:00:00 2001 From: Paul Hovley Date: Fri, 8 Nov 2024 21:01:46 -0700 Subject: [PATCH 2/8] Simplify setting feature enabled for user --- packages/app/src/services/feature.service.ts | 29 ++++++++------------ 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/packages/app/src/services/feature.service.ts b/packages/app/src/services/feature.service.ts index 768b693a..03e6b102 100644 --- a/packages/app/src/services/feature.service.ts +++ b/packages/app/src/services/feature.service.ts @@ -8,25 +8,20 @@ export const isFeatureEnabled = ( state: FeatureState, ): boolean => { const enabledFeatures = JSON.parse( - localStorage.getItem('enabled-features') || '{}', + localStorage.getItem(`enabled-features-${feature}`) || '', ) - return enabledFeatures[feature] === state + return enabledFeatures === state } export const setFeatureEnabled = (feature: FeatureKey, state: FeatureState) => { - const enabledFeatures = JSON.parse( - localStorage.getItem('enabled-features') || '{}', - ) - const newEnabledFeatures = { ...enabledFeatures, [feature]: state } - localStorage.setItem('enabled-features', JSON.stringify(newEnabledFeatures)) - posthog.capture('$set', { - $set: { 'enabled-features': newEnabledFeatures }, - }) -} - -export const getFeaturePreferences = (): Record => { - const enabledFeatures = JSON.parse( - localStorage.getItem('enabled-features') || '{}', - ) - return enabledFeatures + let stringState = '' + try { + stringState = JSON.stringify(state) + localStorage.setItem(`enabled-features-${feature}`, stringState) + posthog.capture('$set', { + $set: { [`enabled-features-${feature}`]: state }, + }) + } catch (error) { + console.error(`Error setting feature enabled-features-${feature}`, error) + } } From 909aa51d1fcc038cd3c458e4252ca9a75ea61748 Mon Sep 17 00:00:00 2001 From: Paul Hovley Date: Fri, 8 Nov 2024 21:08:09 -0700 Subject: [PATCH 3/8] make copy command more robust --- .../common/CodeSnippit/CodeSnippit.tsx | 36 ++++++++++++++----- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/packages/app/src/components/common/CodeSnippit/CodeSnippit.tsx b/packages/app/src/components/common/CodeSnippit/CodeSnippit.tsx index abce81ac..3288b8d2 100644 --- a/packages/app/src/components/common/CodeSnippit/CodeSnippit.tsx +++ b/packages/app/src/components/common/CodeSnippit/CodeSnippit.tsx @@ -28,22 +28,40 @@ export const CodeSnippit = ({ code, onCopy }: CodeSnippitProps) => { } }, []) - const copyToClipboard = () => { + const copyToClipboard = async () => { if (errored || copied) return if (onCopy) onCopy() + if (navigator.clipboard && window.isSecureContext) { + await navigator.clipboard.writeText(code) + setCopied(true) + handleTimer(() => { + setCopied(false) + }) + } else { + const textArea = document.createElement('textarea') + textArea.value = code - if (navigator.clipboard) { - navigator.clipboard.writeText(code)?.then(() => { + textArea.style.position = 'absolute' + textArea.style.left = '-999999px' + + document.body.prepend(textArea) + textArea.select() + + try { + document.execCommand('copy') setCopied(true) handleTimer(() => { setCopied(false) }) - }) - } else { - setErrored(true) - handleTimer(() => { - setErrored(false) - }) + } catch (error) { + setErrored(true) + handleTimer(() => { + setErrored(false) + }) + console.error(error) + } finally { + textArea.remove() + } } } From e88f2eaa6a426d45dae7fb796893db9828581e7f Mon Sep 17 00:00:00 2001 From: Paul Hovley Date: Fri, 8 Nov 2024 21:25:23 -0700 Subject: [PATCH 4/8] Fix generate ai report button --- .../app/src/api/platformServer/weeklyReport.platformApi.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/app/src/api/platformServer/weeklyReport.platformApi.ts b/packages/app/src/api/platformServer/weeklyReport.platformApi.ts index e0d78db6..a2ddbc18 100644 --- a/packages/app/src/api/platformServer/weeklyReport.platformApi.ts +++ b/packages/app/src/api/platformServer/weeklyReport.platformApi.ts @@ -19,13 +19,11 @@ export const useGetAiWeeklyReport = (startOfWeek: string, email?: string) => { export const useGenerateAiWeeklyReport = () => { const queryClient = useQueryClient() - let startOfWeek: string const mutationFn = (body: { email: string startOfWeek: string weeklyReport: CodeClimbers.WeeklyScores }) => { - startOfWeek = body.startOfWeek return platformApiRequest({ url: `${PLATFORM_API_URL}/ai-weekly-report`, method: 'POST', @@ -34,9 +32,9 @@ export const useGenerateAiWeeklyReport = () => { } return useMutation({ mutationFn, - onSuccess: () => { + onSuccess: (_, variables) => { queryClient.invalidateQueries({ - queryKey: weeklyReportKeys.aiWeeklyReports(startOfWeek), + queryKey: weeklyReportKeys.aiWeeklyReports(variables.startOfWeek), }) }, }) From 9bff1895258fa9b785faa82e9ec75e70e5250ace Mon Sep 17 00:00:00 2001 From: Paul Hovley Date: Fri, 8 Nov 2024 21:26:42 -0700 Subject: [PATCH 5/8] remove sentry from backend --- package.json | 2 -- packages/server/package.json | 2 -- packages/server/src/main.ts | 2 -- packages/server/src/sentry.ts | 15 --------------- 4 files changed, 21 deletions(-) delete mode 100644 packages/server/src/sentry.ts diff --git a/package.json b/package.json index 24c859d7..5367c3b8 100644 --- a/package.json +++ b/package.json @@ -58,8 +58,6 @@ "@nivo/bar": "^0.87.0", "@oclif/core": "^4.0.12", "@oclif/plugin-warn-if-update-available": "^3.1.11", - "@sentry/nestjs": "^8.30.0", - "@sentry/profiling-node": "^8.30.0", "@tanstack/react-query": "^5.48.0", "axios": "^1.7.7", "class-transformer": "^0.5.1", diff --git a/packages/server/package.json b/packages/server/package.json index 43f997e6..7909bc85 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -44,8 +44,6 @@ "@nestjs/schedule": "^4.1.1", "@nestjs/serve-static": "^4.0.2", "@oclif/core": "^4.0.17", - "@sentry/nestjs": "^8.25.0", - "@sentry/profiling-node": "^8.25.0", "axios": "^1.7.7", "class-transformer": "^0.5.1", "class-validator": "^0.14.1", diff --git a/packages/server/src/main.ts b/packages/server/src/main.ts index a4b811c3..2607670b 100644 --- a/packages/server/src/main.ts +++ b/packages/server/src/main.ts @@ -1,5 +1,3 @@ -// Import this first! -import './sentry' import { NestFactory } from '@nestjs/core' import { AppModule } from './app.module' import { Logger, ValidationPipe } from '@nestjs/common' diff --git a/packages/server/src/sentry.ts b/packages/server/src/sentry.ts deleted file mode 100644 index c5e52e45..00000000 --- a/packages/server/src/sentry.ts +++ /dev/null @@ -1,15 +0,0 @@ -import * as Sentry from '@sentry/nestjs' -import { nodeProfilingIntegration } from '@sentry/profiling-node' -import { isProd } from '../utils/environment.util' - -if (isProd()) { - Sentry.init({ - dsn: 'https://e885e4c5eeed09d6229c7d7bfdc8d762@o4507772937043968.ingest.us.sentry.io/4507772946022400', - integrations: [nodeProfilingIntegration()], - // Performance Monitoring - tracesSampleRate: 0.1, // Capture 100% of the transactions - - // Set sampling rate for profiling - this is relative to tracesSampleRate - profilesSampleRate: 0.1, - }) -} From c472a0f2e9ab0df722c81c410aca831671962b59 Mon Sep 17 00:00:00 2001 From: Paul Hovley Date: Fri, 8 Nov 2024 21:28:37 -0700 Subject: [PATCH 6/8] remove sentry from backend --- packages/server/src/app.module.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/server/src/app.module.ts b/packages/server/src/app.module.ts index 57f094be..118d907e 100644 --- a/packages/server/src/app.module.ts +++ b/packages/server/src/app.module.ts @@ -5,13 +5,11 @@ import { AllExceptionsFilter } from './filters/allExceptions.filter' import { RequestLoggerMiddleware } from './common/infrastructure/http/middleware/requestlogger.middleware' import { ServeStaticModule } from '@nestjs/serve-static' import { DbModule } from './v1/database/knex' -import { SentryModule } from '@sentry/nestjs/setup' import { APP_DIST_PATH } from '../utils/node.util' import { ScheduledTaskModule } from './common/scheduler.module' @Module({ imports: [ - SentryModule.forRoot(), DbModule, V1Module, ScheduledTaskModule, From 1cb825e7bdd85e84e3a2e4b7a400e3ec26c36e5f Mon Sep 17 00:00:00 2001 From: Paul Hovley Date: Fri, 8 Nov 2024 21:54:12 -0700 Subject: [PATCH 7/8] Add commands for outputing logs to the console --- packages/server/commands/log/error.ts | 26 +++++++++++++++++ packages/server/commands/log/index.ts | 26 +++++++++++++++++ packages/server/utils/node.util.ts | 41 ++++++++++++--------------- 3 files changed, 70 insertions(+), 23 deletions(-) create mode 100644 packages/server/commands/log/error.ts create mode 100644 packages/server/commands/log/index.ts diff --git a/packages/server/commands/log/error.ts b/packages/server/commands/log/error.ts new file mode 100644 index 00000000..03fec6f9 --- /dev/null +++ b/packages/server/commands/log/error.ts @@ -0,0 +1,26 @@ +// oclif command to get the latest 50 lines of error logs from the log file +import { Command, Flags } from '@oclif/core' +import path from 'node:path' +import fs from 'node:fs' +import { CODE_CLIMBER_META_DIR, ERROR_LOG_NAME } from '../../utils/node.util' + +export default class Log extends Command { + static description = 'Get the latest 50 lines of error logs' + + static flags = { + lines: Flags.string({ + char: 'l', + description: 'Number of lines to get', + required: false, + }), + } + + async run() { + const { flags } = await this.parse(Log) + const lines = flags.lines || 50 + this.log(`Getting latest ${lines} lines of error logs...`) + const errorLogPath = path.join(CODE_CLIMBER_META_DIR, ERROR_LOG_NAME) + const errorLogContent = fs.readFileSync(errorLogPath, 'utf8') + this.log(errorLogContent.split('\n').slice(-lines).join('\n')) + } +} diff --git a/packages/server/commands/log/index.ts b/packages/server/commands/log/index.ts new file mode 100644 index 00000000..efdabd39 --- /dev/null +++ b/packages/server/commands/log/index.ts @@ -0,0 +1,26 @@ +// oclif command to get the latest 50 lines of error logs from the log file +import { Command, Flags } from '@oclif/core' +import path from 'node:path' +import fs from 'node:fs' +import { CODE_CLIMBER_META_DIR, LOG_NAME } from '../../utils/node.util' + +export default class Log extends Command { + static description = 'Get the latest 50 lines of error logs' + + static flags = { + lines: Flags.string({ + char: 'l', + description: 'Number of lines to get', + required: false, + }), + } + + async run() { + const { flags } = await this.parse(Log) + const lines = flags.lines || 50 + this.log(`Getting latest ${lines} lines of error logs...`) + const logPath = path.join(CODE_CLIMBER_META_DIR, LOG_NAME) + const logContent = fs.readFileSync(logPath, 'utf8') + this.log(logContent.split('\n').slice(-lines).join('\n')) + } +} diff --git a/packages/server/utils/node.util.ts b/packages/server/utils/node.util.ts index d71c6265..ba7f3ea9 100644 --- a/packages/server/utils/node.util.ts +++ b/packages/server/utils/node.util.ts @@ -20,6 +20,8 @@ interface INodeUtil { PROJECT_ROOT: string BIN_PATH: string START_ERR_LOG_MESSAGE: string + LOG_NAME: string + ERROR_LOG_NAME: string HOME_DIR: string CODE_CLIMBER_META_DIR: string DB_PATH: string @@ -35,8 +37,15 @@ abstract class BaseNodeUtil implements INodeUtil { : path.join(__dirname, '..', '..', '..') BIN_PATH = path.join(this.PROJECT_ROOT, 'bin') HOME_DIR = os.homedir() - - abstract START_ERR_LOG_MESSAGE: string + LOG_NAME = 'codeclimbers.log' + ERROR_LOG_NAME = 'codeclimbers_error.log' + START_ERR_LOG_MESSAGE = pc.red(` + It seems the server is having trouble starting. Run the command + + npx codeclimbers log:error -l 50 + + to investigate the issue further. You can also refer to https://github.com/CodeClimbersIO/cli/blob/release/docs/Troubleshooting.md or message us on our Discord + `) abstract CODE_CLIMBER_META_DIR: string abstract DB_PATH: string APP_DIST_PATH = path.join(this.PROJECT_ROOT, 'packages', 'app', 'dist') @@ -61,13 +70,6 @@ class DarwinNodeUtil extends BaseNodeUtil { this.CODE_CLIMBER_META_DIR, isTest() ? 'codeclimber.test.sqlite' : dbName, ) - START_ERR_LOG_MESSAGE = pc.red(` - It seems the server is having trouble starting. Run the command - - ${pc.white('cat ' + this.CODE_CLIMBER_META_DIR + '/codeclimbers_error.log')} - - to investigate the issue further. You can also refer to https://github.com/CodeClimbersIO/cli/blob/release/docs/Troubleshooting.md or message us on our Discord - `) NODE_PATH = (): string => { const result = execSync('which node').toString().trim() @@ -85,13 +87,8 @@ class WindowsNodeUtil extends BaseNodeUtil { this.CODE_CLIMBER_META_DIR, isTest() ? 'codeclimber.test.sqlite' : 'codeclimber.sqlite', ) - START_ERR_LOG_MESSAGE: string = pc.red(` - It seems the server is having trouble starting. Run the command in cmd (not powershell) - - ${pc.white('more ' + this.CODE_CLIMBER_META_DIR + '\\codeclimbers.err.log')} - - to investigate the issue further. You can also refer to https://github.com/CodeClimbersIO/cli/blob/release/docs/Troubleshooting.md or message us on our Discord - `) + LOG_NAME = 'codeclimbers.out.log' + ERROR_LOG_NAME = 'codeclimbers.err.log' NODE_PATH = (): string => { const result = execSync('where node').toString().trim() @@ -109,13 +106,7 @@ class LinuxNodeUtil extends BaseNodeUtil { this.CODE_CLIMBER_META_DIR, isTest() ? 'codeclimber.test.sqlite' : 'codeclimber.sqlite', ) - START_ERR_LOG_MESSAGE = pc.red(` - It seems the server is having trouble starting. Run the command - - ${pc.white('cat ' + this.CODE_CLIMBER_META_DIR + '/codeclimbers_error.log')} - - to investigate the issue further - `) + NODE_PATH = (): string => { const result = execSync('which node').toString().trim() return path.dirname(result) @@ -146,6 +137,8 @@ export const CODE_CLIMBER_META_DIR = nodeUtil.CODE_CLIMBER_META_DIR export const DB_PATH = nodeUtil.DB_PATH export const APP_DIST_PATH = nodeUtil.APP_DIST_PATH export const CODE_CLIMBER_INI_PATH = nodeUtil.CODE_CLIMBER_INI_PATH +export const LOG_NAME = nodeUtil.LOG_NAME +export const ERROR_LOG_NAME = nodeUtil.ERROR_LOG_NAME export const NODE_PATH = nodeUtil.NODE_PATH export const initDBDir = nodeUtil.initDBDir @@ -160,6 +153,8 @@ const logPaths = () => { Logger.debug(HOME_DIR, 'HOME_DIR') Logger.debug(APP_DIST_PATH, 'APP_DIST_PATH') Logger.debug(CODE_CLIMBER_INI_PATH, 'CODE_CLIMBER_INI_PATH') + Logger.debug(LOG_NAME, 'LOG_NAME') + Logger.debug(ERROR_LOG_NAME, 'ERROR_LOG_NAME') } logPaths() From bddd23e43fcb5450091d7a77028721cc5b737989 Mon Sep 17 00:00:00 2001 From: Paul Hovley Date: Fri, 8 Nov 2024 21:56:45 -0700 Subject: [PATCH 8/8] Added command for outputing standard logs --- packages/server/commands/log/{index.ts => out.ts} | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) rename packages/server/commands/log/{index.ts => out.ts} (82%) diff --git a/packages/server/commands/log/index.ts b/packages/server/commands/log/out.ts similarity index 82% rename from packages/server/commands/log/index.ts rename to packages/server/commands/log/out.ts index efdabd39..37c303b1 100644 --- a/packages/server/commands/log/index.ts +++ b/packages/server/commands/log/out.ts @@ -4,7 +4,7 @@ import path from 'node:path' import fs from 'node:fs' import { CODE_CLIMBER_META_DIR, LOG_NAME } from '../../utils/node.util' -export default class Log extends Command { +export default class LogOut extends Command { static description = 'Get the latest 50 lines of error logs' static flags = { @@ -16,9 +16,9 @@ export default class Log extends Command { } async run() { - const { flags } = await this.parse(Log) + const { flags } = await this.parse(LogOut) const lines = flags.lines || 50 - this.log(`Getting latest ${lines} lines of error logs...`) + this.log(`Getting latest ${lines} lines of logs...`) const logPath = path.join(CODE_CLIMBER_META_DIR, LOG_NAME) const logContent = fs.readFileSync(logPath, 'utf8') this.log(logContent.split('\n').slice(-lines).join('\n'))