diff --git a/README.md b/README.md index a6885d95..e7d4f89b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@

- Worklenz Logo + Worklenz Logo
Worklenz @@ -315,6 +315,7 @@ docker-compose up -d docker-compose down ``` + ## MinIO Integration The project uses MinIO as an S3-compatible object storage service, which provides an open-source alternative to AWS S3 for development and production. @@ -403,6 +404,10 @@ This script generates properly configured environment files for both development - Frontend: http://localhost:5000 - Backend API: http://localhost:3000 (or https://localhost:3000 with SSL) +4. Video Guide + + For a visual walkthrough of the local Docker deployment process, check out our [step-by-step video guide](https://www.youtube.com/watch?v=AfwAKxJbqLg). + ### Remote Server Deployment When deploying to a remote server: @@ -428,6 +433,10 @@ When deploying to a remote server: - Frontend: http://your-server-hostname:5000 - Backend API: http://your-server-hostname:3000 +4. Video Guide + + For a complete walkthrough of deploying Worklenz to a remote server, check out our [deployment video guide](https://www.youtube.com/watch?v=CAZGu2iOXQs&t=10s). + ### Environment Configuration The Docker setup uses environment variables to configure the services: diff --git a/update-docker-env.sh b/update-docker-env.sh index 77ab1beb..7852e86f 100755 --- a/update-docker-env.sh +++ b/update-docker-env.sh @@ -73,8 +73,8 @@ cat > worklenz-backend/.env << EOL NODE_ENV=production PORT=3000 SESSION_NAME=worklenz.sid -SESSION_SECRET=change_me_in_production -COOKIE_SECRET=change_me_in_production +SESSION_SECRET=$(openssl rand -base64 48) +COOKIE_SECRET=$(openssl rand -base64 48) # CORS SOCKET_IO_CORS=${FRONTEND_URL} @@ -123,7 +123,7 @@ SLACK_WEBHOOK= COMMIT_BUILD_IMMEDIATELY=true # JWT Secret -JWT_SECRET=change_me_in_production +JWT_SECRET=$(openssl rand -base64 48) EOL echo "Environment configuration updated for ${HOSTNAME} with" $([ "$USE_SSL" = "true" ] && echo "HTTPS/WSS" || echo "HTTP/WS") @@ -138,4 +138,4 @@ echo "Frontend URL: ${FRONTEND_URL}" echo "API URL: ${HTTP_PREFIX}${HOSTNAME}:3000" echo "Socket URL: ${WS_PREFIX}${HOSTNAME}:3000" echo "MinIO Dashboard URL: ${MINIO_DASHBOARD_URL}" -echo "CORS is configured to allow requests from: ${FRONTEND_URL}" \ No newline at end of file +echo "CORS is configured to allow requests from: ${FRONTEND_URL}" diff --git a/worklenz-frontend/Dockerfile b/worklenz-frontend/Dockerfile index a32f879e..46a87fa7 100644 --- a/worklenz-frontend/Dockerfile +++ b/worklenz-frontend/Dockerfile @@ -12,7 +12,7 @@ COPY . . RUN echo "window.VITE_API_URL='${VITE_API_URL:-http://backend:3000}';" > ./public/env-config.js && \ echo "window.VITE_SOCKET_URL='${VITE_SOCKET_URL:-ws://backend:3000}';" >> ./public/env-config.js -RUN npm run build +RUN NODE_OPTIONS="--max-old-space-size=4096" npm run build FROM node:22-alpine AS production diff --git a/worklenz-frontend/src/components/home-tasks/statusDropdown/home-tasks-status-dropdown.tsx b/worklenz-frontend/src/components/home-tasks/statusDropdown/home-tasks-status-dropdown.tsx index bc75016d..f3595e99 100644 --- a/worklenz-frontend/src/components/home-tasks/statusDropdown/home-tasks-status-dropdown.tsx +++ b/worklenz-frontend/src/components/home-tasks/statusDropdown/home-tasks-status-dropdown.tsx @@ -21,10 +21,10 @@ const HomeTasksStatusDropdown = ({ task, teamId }: HomeTasksStatusDropdownProps) const { socket, connected } = useSocket(); const { homeTasksConfig } = useAppSelector(state => state.homePageReducer); const { - refetch - } = useGetMyTasksQuery(homeTasksConfig, { - skip: true // Skip automatic queries entirely - }); + refetch + } = useGetMyTasksQuery(homeTasksConfig, { + skip: false, // Ensure this query runs + }); const [selectedStatus, setSelectedStatus] = useState(undefined); diff --git a/worklenz-frontend/src/components/home-tasks/taskDatePicker/home-tasks-date-picker.tsx b/worklenz-frontend/src/components/home-tasks/taskDatePicker/home-tasks-date-picker.tsx index 604cbce5..857458ff 100644 --- a/worklenz-frontend/src/components/home-tasks/taskDatePicker/home-tasks-date-picker.tsx +++ b/worklenz-frontend/src/components/home-tasks/taskDatePicker/home-tasks-date-picker.tsx @@ -23,14 +23,14 @@ const HomeTasksDatePicker = ({ record }: HomeTasksDatePickerProps) => { const { t } = useTranslation('home'); const { homeTasksConfig } = useAppSelector(state => state.homePageReducer); const { refetch } = useGetMyTasksQuery(homeTasksConfig, { - skip: true // Skip automatic queries entirely + skip: false }); - + // Use useMemo to avoid re-renders when record.end_date is the same - const initialDate = useMemo(() => + const initialDate = useMemo(() => record.end_date ? dayjs(record.end_date) : null - , [record.end_date]); - + , [record.end_date]); + const [selectedDate, setSelectedDate] = useState(initialDate); // Update selected date when record changes diff --git a/worklenz-frontend/src/pages/home/task-list/tasks-list.tsx b/worklenz-frontend/src/pages/home/task-list/tasks-list.tsx index bd2f605a..cc36de1a 100644 --- a/worklenz-frontend/src/pages/home/task-list/tasks-list.tsx +++ b/worklenz-frontend/src/pages/home/task-list/tasks-list.tsx @@ -89,7 +89,7 @@ const TasksList: React.FC = React.memo(() => { dispatch(getTeamMembers({ index: 0, size: 100, field: null, order: null, search: null, all: true })); }, [dispatch]); - const handleSelectTask = useCallback((task : IMyTask) => { + const handleSelectTask = useCallback((task: IMyTask) => { dispatch(setSelectedTaskId(task.id || '')); dispatch(fetchTask({ taskId: task.id || '', projectId: task.project_id || '' })); dispatch(setProjectId(task.project_id || '')); @@ -155,7 +155,7 @@ const TasksList: React.FC = React.memo(() => { render: (_, record) => { return ( - + {record.project_name} @@ -271,10 +271,10 @@ const TasksList: React.FC = React.memo(() => { columns={columns as TableProps['columns']} size="middle" rowClassName={() => 'custom-row-height'} - loading={homeTasksFetching && !skipAutoRefetch} + loading={homeTasksFetching && skipAutoRefetch} pagination={false} /> - +