diff --git a/.cspell.json b/.cspell.json index e77472231..cd7d666ff 100644 --- a/.cspell.json +++ b/.cspell.json @@ -5,6 +5,7 @@ "words": [ "barcodes", "cacheable", + "camelcase", "cloudinary", "clsxm", "dummyimage", @@ -14,6 +15,8 @@ "headlessui", "heroicons", "JITSU", + "kanban", + "passcode", "plasmo", "RECAPTCHA", "svgs", @@ -54,7 +57,13 @@ "docker-compose.demo.yml", "docker-compose.yml", "wait", + "signin", + "Chatwoot", + "CHATWOOT", "apps/web/lib/i18n/*.ts", - "apps/mobile/app/i18n/*.ts" + "apps/web/public/locales/**", + "apps/mobile/app/i18n/*.ts", + "apps/mobile/android/**", + "apps/mobile/ios/**" ] } diff --git a/.gitignore b/.gitignore index 425c699ed..4f744ed77 100644 --- a/.gitignore +++ b/.gitignore @@ -69,3 +69,6 @@ Thumbs.db /apps/**/.cache /packages/**/.cache /packages/**/dist + +# Local Netlify folder +.netlify diff --git a/Dockerfile b/Dockerfile index 016acfb61..0520af00c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,12 +4,19 @@ ARG NODE_VERSION=18.17.1 FROM node:${NODE_VERSION}-slim as base - # Next.js app lives here WORKDIR /app -# Set production environment -ENV NEXT_SHARP_PATH=/app/node_modules/sharp +ENV NEXT_TELEMETRY_DISABLED=1 +ENV NEXT_BUILD_OUTPUT_TYPE=standalone +ENV NEXT_SHARP_PATH=/temp/node_modules/sharp + +RUN npm i -g npm@latest +# Install sharp, NextJS image optimization +RUN mkdir /temp && cd /temp && \ + npm i sharp + +RUN npm cache clean --force # Throw-away build stage to reduce size of final image @@ -33,7 +40,7 @@ RUN cd apps/web && \ # Copy application code COPY --link . . -ENV NODE_ENV="production" +ENV NODE_ENV=production # Build application RUN yarn run build:web @@ -42,16 +49,22 @@ RUN yarn run build:web RUN cd apps/web && \ yarn install --prod --ignore-scripts +RUN yarn cache clean + # Final stage for app image FROM base -ENV NODE_ENV="production" +ENV NODE_ENV=production # Copy built application -COPY --from=build /app /app +COPY --from=build /app/apps/web/.next/standalone ./ +COPY --from=build /app/apps/web/.next/static ./apps/web/.next/static +COPY --from=build /app/apps/web/public ./apps/web/public # Start the server by default, this can be overwritten at runtime EXPOSE 3000 -CMD [ "npm", "run", "start:web" ] +ENV PORT=3000 + +CMD [ "node", "./apps/web/server.js" ] diff --git a/README.md b/README.md index d6adff5d0..425d51340 100644 --- a/README.md +++ b/README.md @@ -138,9 +138,15 @@ WIP ### Railway -Note: WIP +[![Deploy on Railway](https://railway.app/button.svg)](https://railway.app/template/7_OfzR?referralCode=40jeja) -[![Deploy on Railway](https://railway.app/button.svg)](https://railway.app/template/EverTeams) +### Fly + +[![Deploy on Railway](https://ever.team/fly.png)](https://github.com/ever-co/ever-teams/wiki/Deploy-to-Fly) + +### Netlify + +[![Deploy to Netlify](https://www.netlify.com/img/deploy/button.svg)](https://app.netlify.com/start/deploy?repository=https://github.com/ever-co/ever-teams) ## 📄 Content @@ -164,8 +170,8 @@ Note: WIP ## 🔐 Security -Ever Teams Platform follows good security practices, but 100% security cannot be guaranteed in any software! -Ever Teams Platform is provided AS IS without any warranty. Use at your own risk! +**Ever Teams Platform** follows good security practices, but 100% security cannot be guaranteed in any software! +**Ever Teams Platform** is provided AS IS without any warranty. Use at your own risk! See more details in the [LICENSE.md](LICENSE.md). In a production setup, all client-side to server-side (backend, APIs) communications should be encrypted using HTTPS/WSS/SSL (REST APIs, GraphQL endpoint, Socket.io WebSockets, etc.). diff --git a/apps/extensions/assets/logo/gauzy-teams-dark.png b/apps/extensions/assets/logo/ever-teams-dark.png similarity index 100% rename from apps/extensions/assets/logo/gauzy-teams-dark.png rename to apps/extensions/assets/logo/ever-teams-dark.png diff --git a/apps/extensions/components/popup/Header.tsx b/apps/extensions/components/popup/Header.tsx index 7f96ad2da..3c79004f6 100644 --- a/apps/extensions/components/popup/Header.tsx +++ b/apps/extensions/components/popup/Header.tsx @@ -1,5 +1,5 @@ import classNames from 'classnames'; -import logoImg from 'data-base64:~assets/logo/gauzy-teams-dark.png'; +import logoImg from 'data-base64:~assets/logo/ever-teams-dark.png'; import React, { FC, useState } from 'react'; import AppDropdown from '~components/shared/AppDropdown'; diff --git a/apps/mobile/android/app/build.gradle b/apps/mobile/android/app/build.gradle index f5e56efee..907eb40da 100644 --- a/apps/mobile/android/app/build.gradle +++ b/apps/mobile/android/app/build.gradle @@ -118,7 +118,7 @@ android { applicationId 'ever.team' minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1 + versionCode 2 versionName "0.1.0" } diff --git a/apps/mobile/android/app/src/main/AndroidManifest.xml b/apps/mobile/android/app/src/main/AndroidManifest.xml index eaaa246de..80f5e741c 100644 --- a/apps/mobile/android/app/src/main/AndroidManifest.xml +++ b/apps/mobile/android/app/src/main/AndroidManifest.xml @@ -15,10 +15,10 @@ - + - + @@ -33,4 +33,4 @@ - + \ No newline at end of file diff --git a/apps/mobile/android/app/src/main/res/values/strings.xml b/apps/mobile/android/app/src/main/res/values/strings.xml index be1d463f8..54ccbc9f2 100644 --- a/apps/mobile/android/app/src/main/res/values/strings.xml +++ b/apps/mobile/android/app/src/main/res/values/strings.xml @@ -2,5 +2,5 @@ Ever Teams cover false - 1.0.0 - + exposdk:48.0.0 + \ No newline at end of file diff --git a/apps/mobile/app.json b/apps/mobile/app.json index 81e750d65..ddc1e642f 100644 --- a/apps/mobile/app.json +++ b/apps/mobile/app.json @@ -3,10 +3,10 @@ "displayName": "Ever Teams", "expo": { "name": "Ever Teams", - "slug": "ever-gauzy-teams-mobile-expo", + "slug": "ever-teams-mobile", "version": "0.1.0", "orientation": "portrait", - "icon": "./assets/images/gauzy-teams-logo.png", + "icon": "./assets/images/ever-teams-logo.png", "splash": { "image": "./assets/images/splash-ever-teams.png", "resizeMode": "cover", @@ -15,7 +15,7 @@ "owner": "everco", "updates": { "fallbackToCacheTimeout": 0, - "url": "https://u.expo.dev/9f38f768-16f6-4c47-b354-9745ebda1335" + "url": "https://u.expo.dev/2ff924e4-7a91-4b23-9db9-7453a8063bb0" }, "jsEngine": "hermes", "assetBundlePatterns": ["**/*"], @@ -74,7 +74,7 @@ }, "extra": { "eas": { - "projectId": "9f38f768-16f6-4c47-b354-9745ebda1335" + "projectId": "2ff924e4-7a91-4b23-9db9-7453a8063bb0" } }, "hooks": { diff --git a/apps/mobile/app/components/IssuesModal.tsx b/apps/mobile/app/components/IssuesModal.tsx index 40e11202b..b78ff7f42 100644 --- a/apps/mobile/app/components/IssuesModal.tsx +++ b/apps/mobile/app/components/IssuesModal.tsx @@ -1,5 +1,6 @@ /* eslint-disable react-native/no-color-literals */ -import React, { FC, useState } from 'react'; +/* eslint-disable react-native/no-inline-styles */ +import React, { FC, useState } from "react" import { Text, View, @@ -9,56 +10,93 @@ import { Modal, ViewStyle, TouchableWithoutFeedback, - TouchableOpacity -} from 'react-native'; -import { useTaskIssue } from '../services/hooks/features/useTaskIssue'; -import { ITeamTask } from '../services/interfaces/ITask'; -import { SvgUri } from 'react-native-svg'; -import { IIssueType } from '../services/interfaces/ITaskIssue'; -import { useTeamTasks } from '../services/hooks/features/useTeamTasks'; + TouchableOpacity, +} from "react-native" +import { useTaskIssue } from "../services/hooks/features/useTaskIssue" +import { ITeamTask } from "../services/interfaces/ITask" +import { SvgUri } from "react-native-svg" +import { IIssueType } from "../services/interfaces/ITaskIssue" +import { useTeamTasks } from "../services/hooks/features/useTeamTasks" +import { useAppTheme } from "../theme" interface IssuesModalProps { - task: ITeamTask; - readonly?: boolean; + task: ITeamTask + readonly?: boolean + nameIncluded?: boolean + responsiveFontSize?: () => number } -const IssuesModal: FC = ({ task, readonly = false }) => { - const { allTaskIssues } = useTaskIssue(); - const [isModalOpen, setIsModalOpen] = useState(false); - const { updateTask } = useTeamTasks(); +const IssuesModal: FC = ({ + task, + readonly = false, + nameIncluded, + responsiveFontSize, +}) => { + const { allTaskIssues } = useTaskIssue() + const [isModalOpen, setIsModalOpen] = useState(false) + const { updateTask } = useTeamTasks() + const { colors } = useAppTheme() const currentIssue = task?.issueType ? allTaskIssues.find((issue) => issue.name === task?.issueType) - : allTaskIssues.find((issue) => issue.name === 'Task'); + : allTaskIssues.find((issue) => issue.name === "Task") const onChangeIssue = async (text) => { if (task) { const taskEdit = { ...task, - issueType: text - }; + issueType: text, + } - await updateTask(taskEdit, task.id); + await updateTask(taskEdit, task.id) } - }; + } - const iconDimension: number = currentIssue?.name === 'Bug' ? 15 : currentIssue?.name === 'Story' ? 14 : 13; + const iconDimension: number = + currentIssue?.name === "Bug" ? 15 : currentIssue?.name === "Story" ? 14 : 13 return ( <> { - if (currentIssue.name !== 'Epic' && !readonly) { - setIsModalOpen(true); + if (currentIssue.name !== "Epic" && !readonly) { + setIsModalOpen(true) } }} > - + + + {nameIncluded && ( + + {currentIssue?.name} + + )} setIsModalOpen(false)}> - + ( @@ -73,58 +111,60 @@ const IssuesModal: FC = ({ task, readonly = false }) => { - ); -}; + ) +} -export default IssuesModal; +export default IssuesModal const ModalPopUp = ({ visible, children, onDismiss }) => { - const [showModal, setShowModal] = React.useState(visible); - const scaleValue = React.useRef(new Animated.Value(0)).current; + const [showModal, setShowModal] = React.useState(visible) + const scaleValue = React.useRef(new Animated.Value(0)).current React.useEffect(() => { - toggleModal(); - }, [visible]); + toggleModal() + }, [visible]) const toggleModal = () => { if (visible) { - setShowModal(true); + setShowModal(true) Animated.spring(scaleValue, { toValue: 1, - useNativeDriver: true - }).start(); + useNativeDriver: true, + }).start() } else { - setTimeout(() => setShowModal(false), 200); + setTimeout(() => setShowModal(false), 200) Animated.timing(scaleValue, { toValue: 0, duration: 300, - useNativeDriver: true - }).start(); + useNativeDriver: true, + }).start() } - }; + } return ( onDismiss()}> - {children} + + {children} + - ); -}; + ) +} interface IItem { - issue: IIssueType; - onChangeIssue: (text: string) => void; - closeModal: () => void; - readonly?: boolean; + issue: IIssueType + onChangeIssue: (text: string) => void + closeModal: () => void + readonly?: boolean } const Item = ({ issue, onChangeIssue, closeModal, readonly = false }: IItem) => { return ( { - onChangeIssue(issue.name); - closeModal(); + onChangeIssue(issue.name) + closeModal() }} activeOpacity={readonly ? 1 : 0.2} > @@ -132,48 +172,46 @@ const Item = ({ issue, onChangeIssue, closeModal, readonly = false }: IItem) => style={[ styles.issueContainer, { - backgroundColor: issue.color - } + backgroundColor: issue.color, + }, ]} > {issue.name} - ); -}; + ) +} const $modalBackGround: ViewStyle = { flex: 1, - backgroundColor: '#000000AA', - justifyContent: 'center' -}; + backgroundColor: "#000000AA", + justifyContent: "center", +} const styles = StyleSheet.create({ issueContainer: { - alignItems: 'center', + alignItems: "center", borderRadius: 10, - display: 'flex', - flexDirection: 'row', - justifyContent: 'flex-start', + display: "flex", + flexDirection: "row", + justifyContent: "flex-start", marginVertical: 7, paddingHorizontal: 25, - paddingVertical: 20 + paddingVertical: 20, }, - issueText: { color: '#FFFF', fontSize: 22, marginHorizontal: 8 }, + issueText: { color: "#FFFF", fontSize: 22, marginHorizontal: 8 }, modalContainer: { - alignSelf: 'center', - backgroundColor: '#fff', + alignSelf: "center", + backgroundColor: "#fff", borderRadius: 20, - height: 'auto', + height: "auto", padding: 22, - width: '40%' + width: "40%", }, wrapButton: { - alignItems: 'center', + alignItems: "center", borderRadius: 3, - height: 20, - justifyContent: 'center', - width: 20 - } -}); + justifyContent: "center", + }, +}) diff --git a/apps/mobile/app/components/Task/TitleBlock/CreateParentTaskModal.tsx b/apps/mobile/app/components/Task/TitleBlock/CreateParentTaskModal.tsx new file mode 100644 index 000000000..8356d53af --- /dev/null +++ b/apps/mobile/app/components/Task/TitleBlock/CreateParentTaskModal.tsx @@ -0,0 +1,238 @@ +/* eslint-disable react-native/no-inline-styles */ +/* eslint-disable react-native/no-color-literals */ +import { + View, + Text, + Animated, + Modal, + TouchableWithoutFeedback, + ViewStyle, + StyleSheet, + ActivityIndicator, + Pressable, + TextInput, +} from "react-native" +import React, { useCallback, useEffect, useRef, useState } from "react" +import ComboBox from "../../../screens/Authenticated/TimerScreen/components/ComboBox" +import { translate } from "../../../i18n" +import IssuesModal from "../../IssuesModal" +import { useStores } from "../../../models" +import { useTaskInput } from "../../../services/hooks/features/useTaskInput" +import { typography, useAppTheme } from "../../../theme" +import { Feather } from "@expo/vector-icons" +import { ITeamTask } from "../../../services/interfaces/ITask" + +interface ICreateParentTaskModal { + visible: boolean + onDismiss: () => void + task: ITeamTask +} + +const CreateParentTaskModal: React.FC = ({ visible, onDismiss, task }) => { + const { colors } = useAppTheme() + + const taskInput = useTaskInput() + const { + setEditMode, + setQuery, + activeTask, + editMode, + // isModalOpen, + hasCreateForm, + handleTaskCreation, + createLoading, + } = taskInput + + const [combxShow, setCombxShow] = useState(true) + const inputRef = useRef(null) + const { + TimerStore: { localTimerStatus }, + } = useStores() + + const closeCombox = useCallback(() => { + setCombxShow(false) + }, [setCombxShow]) + + useEffect(() => { + setEditMode(true) + setCombxShow(true) + }, [editMode, combxShow]) + + useEffect(() => { + if (!editMode) { + inputRef.current?.blur() + } + }, [editMode]) + + return ( + + + + + + + {!editMode && activeTask ? `#${activeTask.taskNumber} ` : ""} + + setEditMode(true)} + // onBlur={() => setEditMode(false)} + onChangeText={(newText) => setQuery(newText)} + /> + {hasCreateForm && editMode && !createLoading ? ( + { + handleTaskCreation() + // setEditMode(false) + }} + > + + + ) : null} + + {createLoading ? ( + + ) : null} + + {combxShow && ( + + )} + + + ) +} + +export default CreateParentTaskModal + +const ModalPopUp = ({ visible, children, onDismiss }) => { + const [showModal, setShowModal] = React.useState(visible) + const scaleValue = React.useRef(new Animated.Value(0)).current + const modalRef = useRef(null) + + React.useEffect(() => { + toggleModal() + }, [visible]) + const toggleModal = () => { + if (visible) { + setShowModal(true) + Animated.spring(scaleValue, { + toValue: 1, + useNativeDriver: true, + }).start() + } else { + setTimeout(() => setShowModal(false), 200) + Animated.timing(scaleValue, { + toValue: 0, + duration: 300, + useNativeDriver: true, + }).start() + } + } + + const handlePressOutside = (event) => { + const { locationX, locationY } = event.nativeEvent + + if (modalRef.current) { + modalRef.current.measureInWindow((x, y, width, height) => { + if ( + locationX < x || + locationX > x + width || + locationY < y || + locationY > y + height + ) { + onDismiss() + } + }) + } + } + return ( + + + + + {children} + + + + + ) +} + +const $modalBackGround: ViewStyle = { + flex: 1, + backgroundColor: "#000000AA", + justifyContent: "center", +} + +const styles = StyleSheet.create({ + container: { + alignSelf: "center", + borderRadius: 20, + padding: 20, + width: "90%", + }, + loading: { + right: 10, + }, + taskNumberStyle: { + color: "#7B8089", + fontFamily: typography.primary.semiBold, + fontSize: 14, + marginLeft: 5, + }, + textInput: { + backgroundColor: "#fff", + borderRadius: 10, + color: "rgba(40, 32, 72, 0.4)", + fontFamily: typography.fonts.PlusJakartaSans.semiBold, + fontSize: 12, + height: 43, + paddingHorizontal: 6, + paddingVertical: 13, + width: "80%", + }, + wrapInput: { + backgroundColor: "#fff", + borderColor: "rgba(0, 0, 0, 0.1)", + borderRadius: 10, + borderWidth: 1, + height: 45, + paddingHorizontal: 16, + paddingVertical: 2, + width: "100%", + }, +}) diff --git a/apps/mobile/app/components/Task/TitleBlock/index.tsx b/apps/mobile/app/components/Task/TitleBlock/index.tsx index e78de6f1b..2adf6a770 100644 --- a/apps/mobile/app/components/Task/TitleBlock/index.tsx +++ b/apps/mobile/app/components/Task/TitleBlock/index.tsx @@ -1,17 +1,24 @@ /* eslint-disable react-native/no-inline-styles */ /* eslint-disable react-native/no-color-literals */ -import { View, TextInput, StyleSheet, TouchableOpacity } from "react-native" +import { View, TextInput, StyleSheet, TouchableOpacity, Text, Dimensions } from "react-native" import React, { SetStateAction, useCallback, useEffect, useState } from "react" import { useStores } from "../../../models" -import { useAppTheme } from "../../../theme" +import { typography, useAppTheme } from "../../../theme" import { SvgXml } from "react-native-svg" import * as Clipboard from "expo-clipboard" import { closeIconLight, copyIcon, editIcon, tickIconLight } from "../../svgs/icons" import { useTeamTasks } from "../../../services/hooks/features/useTeamTasks" import { showMessage } from "react-native-flash-message" import { translate } from "../../../i18n" +import IssuesModal from "../../IssuesModal" +import { ITeamTask } from "../../../services/interfaces/ITask" +import { limitTextCharaters } from "../../../helpers/sub-text" +import CreateParentTaskModal from "./CreateParentTaskModal" +import { observer } from "mobx-react-lite" +import { useNavigation } from "@react-navigation/native" +import { SettingScreenNavigationProp } from "../../../navigators/AuthenticatedNavigator" -const TaskTitleBlock = () => { +const TaskTitleBlock = observer(() => { const { TaskStore: { detailedTask: task }, } = useStores() @@ -23,6 +30,8 @@ const TaskTitleBlock = () => { const { updateTitle } = useTeamTasks() + const { width } = Dimensions.get("window") + const saveTitle = useCallback((newTitle: string) => { if (newTitle.length > 255) { showMessage({ @@ -51,8 +60,22 @@ const TaskTitleBlock = () => { }) } + const responsiveFontSize = (): number => { + const baseWidth = 428 + const scale = width / baseWidth + const baseFontSize = 10 + + const fontSize = Math.round(baseFontSize * scale) + + if (fontSize < 10) { + return 10 + } + + return fontSize + } + return ( - + { { color: colors.primary, borderColor: edit ? (dark ? "#464242" : "#e5e7eb") : "transparent", + fontFamily: typography.fonts.PlusJakartaSans.semiBold, }, ]} onChangeText={(text) => setTitle(text)} @@ -75,9 +99,42 @@ const TaskTitleBlock = () => { saveTitle={() => saveTitle(title)} /> + + + #{task?.number} + + + + {task?.issueType !== "Epic" && ( + + )} + + {(!task?.issueType || task?.issueType === "Task" || task?.issueType === "Bug") && + task?.rootEpic && + task?.parentId !== task?.rootEpic.id && ( + + )} + + + + + ) -} +}) export default TaskTitleBlock @@ -131,6 +188,118 @@ const TitleIcons: React.FC = ({ dark, edit, setEdit, copyTitle, sav ) } +const ParentTaskBadge: React.FC<{ task: ITeamTask; responsiveFontSize: () => number }> = observer( + ({ task, responsiveFontSize }) => { + const navigation = useNavigation>() + + const { width } = Dimensions.get("window") + + const navigateToParent = (): void => { + navigation.navigate("TaskScreen", { taskId: task?.parentId || task?.parent.id }) + } + return task?.parentId && task?.parent ? ( + + + + #{task?.parent?.taskNumber || task?.parent.number} + + {` - ${limitTextCharaters({ + text: task?.parent?.title, + numChars: width < 391 ? 8 : width <= 410 ? 12 : 18, + })}`} + + + ) : ( + <> + ) + }, +) + +const ParentTaskInput: React.FC<{ task: ITeamTask; responsiveFontSize: () => number }> = observer( + ({ task, responsiveFontSize }) => { + const [modalVisible, setModalVisible] = useState(false) + return task && task?.issueType !== "Epic" ? ( + setModalVisible(true)} + > + + {task?.parentId + ? translate("taskDetailsScreen.changeParent") + : "+ " + translate("taskDetailsScreen.addParent")} + + + setModalVisible(false)} + task={task} + /> + + ) : ( + <> + ) + }, +) + const styles = StyleSheet.create({ copyButton: { alignItems: "center", @@ -152,6 +321,15 @@ const styles = StyleSheet.create({ borderWidth: 1, padding: 3, }, + taskNumber: { + alignItems: "center", + backgroundColor: "#D6D6D6", + borderRadius: 3, + height: 24, + justifyContent: "center", + paddingHorizontal: 8, + paddingVertical: 2, + }, textInput: { borderRadius: 5, borderWidth: 1, diff --git a/apps/mobile/app/helpers/sub-text.tsx b/apps/mobile/app/helpers/sub-text.ts similarity index 100% rename from apps/mobile/app/helpers/sub-text.tsx rename to apps/mobile/app/helpers/sub-text.ts diff --git a/apps/mobile/app/i18n/ar.ts b/apps/mobile/app/i18n/ar.ts index 9f7b943f9..58422e238 100644 --- a/apps/mobile/app/i18n/ar.ts +++ b/apps/mobile/app/i18n/ar.ts @@ -95,6 +95,8 @@ const ar: Translations = { characterLimitErrorTitle: "لم نتمكن من تحديث عنوان المهمة.", characterLimitErrorDescription: "لا يمكن أن يتجاوز عنوان المهمة 255 حرفًا.", copyTitle: "تم نسخ العنوان.", + changeParent: "تغيير الوالدين", + addParent: "أضف أحد الوالدين", }, tasksScreen: { name: "مهام", diff --git a/apps/mobile/app/i18n/bg.ts b/apps/mobile/app/i18n/bg.ts index 9f1b1f4b3..1b6fc8259 100644 --- a/apps/mobile/app/i18n/bg.ts +++ b/apps/mobile/app/i18n/bg.ts @@ -91,6 +91,8 @@ const bg = { characterLimitErrorTitle: "We couldn't update Task Title.", characterLimitErrorDescription: "Task title can't exceed 255 characters.", copyTitle: "Title Copied.", + changeParent: "Change Parent", + addParent: "Add Parent", }, tasksScreen: { name: "Tasks", diff --git a/apps/mobile/app/i18n/en.ts b/apps/mobile/app/i18n/en.ts index e9a2414c8..2ad2082fa 100644 --- a/apps/mobile/app/i18n/en.ts +++ b/apps/mobile/app/i18n/en.ts @@ -92,6 +92,8 @@ const en = { characterLimitErrorTitle: "We couldn't update Task Title.", characterLimitErrorDescription: "Task title can't exceed 255 characters.", copyTitle: "Title Copied.", + changeParent: "Change Parent", + addParent: "Add Parent", }, tasksScreen: { name: "Tasks", diff --git a/apps/mobile/app/i18n/es.ts b/apps/mobile/app/i18n/es.ts index 3e0bbcde9..cfb450cd0 100644 --- a/apps/mobile/app/i18n/es.ts +++ b/apps/mobile/app/i18n/es.ts @@ -91,6 +91,8 @@ const es = { characterLimitErrorTitle: "We couldn't update Task Title.", characterLimitErrorDescription: "Task title can't exceed 255 characters.", copyTitle: "Title Copied.", + changeParent: "Change Parent", + addParent: "Add Parent", }, tasksScreen: { name: "Tasks", diff --git a/apps/mobile/app/i18n/fr.ts b/apps/mobile/app/i18n/fr.ts index d419eff47..53f5d6c86 100644 --- a/apps/mobile/app/i18n/fr.ts +++ b/apps/mobile/app/i18n/fr.ts @@ -94,6 +94,8 @@ const fr = { characterLimitErrorTitle: "Nous n'avons pas pu mettre à jour le titre de la tâche.", characterLimitErrorDescription: "Le titre de la tâche ne peut pas dépasser 255 caractères.", copyTitle: "Titre copié.", + changeParent: "Changer de parent", + addParent: "Ajouter un parent", }, tasksScreen: { name: "Tâches", diff --git a/apps/mobile/app/i18n/he.ts b/apps/mobile/app/i18n/he.ts index 3e189e982..d8a5cd820 100644 --- a/apps/mobile/app/i18n/he.ts +++ b/apps/mobile/app/i18n/he.ts @@ -91,6 +91,8 @@ const he = { characterLimitErrorTitle: "We couldn't update Task Title.", characterLimitErrorDescription: "Task title can't exceed 255 characters.", copyTitle: "Title Copied.", + changeParent: "Change Parent", + addParent: "Add Parent", }, tasksScreen: { name: "Tasks", diff --git a/apps/mobile/app/i18n/ko.ts b/apps/mobile/app/i18n/ko.ts index a5d2d4ac0..1129759a8 100644 --- a/apps/mobile/app/i18n/ko.ts +++ b/apps/mobile/app/i18n/ko.ts @@ -94,6 +94,8 @@ const ko: Translations = { characterLimitErrorTitle: "작업 제목을 업데이트할 수 없습니다.", characterLimitErrorDescription: "작업 제목은 255자를 초과할 수 없습니다.", copyTitle: "제목이 복사되었습니다.", + changeParent: "상위 변경", + addParent: "상위 추가", }, tasksScreen: { name: "작업", diff --git a/apps/mobile/app/i18n/ru.ts b/apps/mobile/app/i18n/ru.ts index 92502220a..1d0117d5d 100644 --- a/apps/mobile/app/i18n/ru.ts +++ b/apps/mobile/app/i18n/ru.ts @@ -91,6 +91,8 @@ const ru = { characterLimitErrorTitle: "We couldn't update Task Title.", characterLimitErrorDescription: "Task title can't exceed 255 characters.", copyTitle: "Title Copied.", + changeParent: "Change Parent", + addParent: "Add Parent", }, tasksScreen: { name: "Tasks", diff --git a/apps/mobile/app/screens/Authenticated/TaskScreen/index.tsx b/apps/mobile/app/screens/Authenticated/TaskScreen/index.tsx index db3592e6c..dfe3deaff 100644 --- a/apps/mobile/app/screens/Authenticated/TaskScreen/index.tsx +++ b/apps/mobile/app/screens/Authenticated/TaskScreen/index.tsx @@ -23,7 +23,7 @@ export const AuthenticatedTaskScreen: FC unknown; - setEditMode: (val: boolean) => void; + tasksHandler: RTuseTaskInput + closeCombo: () => unknown + setEditMode: (val: boolean) => void + parentTasksFilter?: boolean + childTask?: ITeamTask + onDismiss?: () => void } -const ComboBox: FC = observer(function ComboBox({ tasksHandler, closeCombo, setEditMode }) { - const { colors } = useAppTheme(); - const [isScrolling, setIsScrolling] = useState(false); +const ComboBox: FC = observer(function ComboBox({ + tasksHandler, + closeCombo, + setEditMode, + parentTasksFilter, + childTask, + onDismiss, +}) { + const { colors } = useAppTheme() + const [isScrolling, setIsScrolling] = useState(false) return ( @@ -29,27 +40,27 @@ const ComboBox: FC = observer(function ComboBox({ tasksHandler, closeComb onPress={() => tasksHandler.handleTaskCreation()} style={[ styles.createTaskBtn, - { backgroundColor: colors.background, borderColor: colors.secondary } + { backgroundColor: colors.background, borderColor: colors.secondary }, ]} > - {translate('myWorkScreen.tabCreateTask')} + {translate("myWorkScreen.tabCreateTask")} - tasksHandler.setFilter('open')}> + tasksHandler.setFilter("open")}> - tasksHandler.setFilter('closed')}> + tasksHandler.setFilter("closed")}> @@ -58,9 +69,16 @@ const ComboBox: FC = observer(function ComboBox({ tasksHandler, closeComb onScrollBeginDrag={() => setIsScrolling(true)} onScrollEndDrag={() => setIsScrolling(false)} showsVerticalScrollIndicator={false} - data={tasksHandler.filteredTasks} + data={ + parentTasksFilter + ? tasksHandler.filteredEpicTasks + : tasksHandler.filteredTasks + } renderItem={({ item, index }) => ( tasksHandler.handleReopenTask(item)} task={item} @@ -74,40 +92,40 @@ const ComboBox: FC = observer(function ComboBox({ tasksHandler, closeComb - ); -}); + ) +}) const styles = StyleSheet.create({ createTaskBtn: { - alignItems: 'center', + alignItems: "center", borderRadius: 10, borderWidth: 1.5, - flexDirection: 'row', + flexDirection: "row", height: 33, - justifyContent: 'center', + justifyContent: "center", paddingLeft: 24, paddingRight: 16, - width: '100%' + width: "100%", }, createTaskTxt: { - color: '#3826A6', + color: "#3826A6", fontFamily: typography.fonts.PlusJakartaSans.semiBold, fontSize: 10, - lineHeight: 12.6 + lineHeight: 12.6, }, filterSection: { - flexDirection: 'row', - justifyContent: 'space-between', + flexDirection: "row", + justifyContent: "space-between", marginTop: 26, paddingBottom: 16, - width: 232 + width: 232, }, mainContainer: { marginTop: 16, - width: '100%', - zIndex: 5 - } -}); + width: "100%", + zIndex: 5, + }, +}) -export default ComboBox; +export default ComboBox diff --git a/apps/mobile/app/screens/Authenticated/TimerScreen/components/IndividualTask.tsx b/apps/mobile/app/screens/Authenticated/TimerScreen/components/IndividualTask.tsx index 9acd7f564..6d9639bbb 100644 --- a/apps/mobile/app/screens/Authenticated/TimerScreen/components/IndividualTask.tsx +++ b/apps/mobile/app/screens/Authenticated/TimerScreen/components/IndividualTask.tsx @@ -1,72 +1,114 @@ /* eslint-disable react-native/no-inline-styles */ /* eslint-disable react-native/no-color-literals */ -import React, { FC, useMemo, useState } from 'react'; -import { View, StyleSheet, Text, ImageStyle, TouchableOpacity } from 'react-native'; -import { Entypo, EvilIcons } from '@expo/vector-icons'; -import { GLOBAL_STYLE as GS } from '../../../../../assets/ts/styles'; -import { colors, spacing, typography, useAppTheme } from '../../../../theme'; -import DeletePopUp from './DeletePopUp'; -import { ITeamTask } from '../../../../services/interfaces/ITask'; -import { observer } from 'mobx-react-lite'; -import TaskStatus from '../../../../components/TaskStatus'; -import { useTeamTasks } from '../../../../services/hooks/features/useTeamTasks'; -import IssuesModal from '../../../../components/IssuesModal'; -import { limitTextCharaters } from '../../../../helpers/sub-text'; -import { Avatar } from 'react-native-paper'; -import { imgTitleProfileAvatar } from '../../../../helpers/img-title-profile-avatar'; +import React, { FC, useCallback, useMemo, useState } from "react" +import { View, StyleSheet, Text, ImageStyle, TouchableOpacity } from "react-native" +import { Entypo, EvilIcons } from "@expo/vector-icons" +import { GLOBAL_STYLE as GS } from "../../../../../assets/ts/styles" +import { colors, spacing, typography, useAppTheme } from "../../../../theme" +import DeletePopUp from "./DeletePopUp" +import { ITeamTask } from "../../../../services/interfaces/ITask" +import { observer } from "mobx-react-lite" +import TaskStatus from "../../../../components/TaskStatus" +import { useTeamTasks } from "../../../../services/hooks/features/useTeamTasks" +import IssuesModal from "../../../../components/IssuesModal" +import { limitTextCharaters } from "../../../../helpers/sub-text" +import { Avatar } from "react-native-paper" +import { imgTitleProfileAvatar } from "../../../../helpers/img-title-profile-avatar" +import { cloneDeep } from "lodash" export interface Props { - task: ITeamTask; - handleActiveTask: (value: ITeamTask) => unknown; - closeCombo?: () => unknown; - onReopenTask: () => unknown; - setEditMode: (val: boolean) => void; - isScrolling: boolean; + task: ITeamTask + handleActiveTask: (value: ITeamTask) => unknown + closeCombo?: () => unknown + onReopenTask: () => unknown + setEditMode: (val: boolean) => void + isScrolling: boolean + parentTasksFilter: boolean + childTask?: ITeamTask + onDismiss?: () => void } const IndividualTask: FC = observer( - ({ task, handleActiveTask, closeCombo, onReopenTask, setEditMode, isScrolling }) => { - const { colors } = useAppTheme(); - const [showDel, setShowDel] = useState(false); - const { updateTask } = useTeamTasks(); + ({ + task, + handleActiveTask, + closeCombo, + onReopenTask, + setEditMode, + isScrolling, + parentTasksFilter, + childTask, + onDismiss, + }) => { + const { colors } = useAppTheme() + const [showDel, setShowDel] = useState(false) + const { updateTask } = useTeamTasks() const onCloseTask = async () => { await updateTask( { ...task, - status: 'closed' + status: "closed", }, - task.id - ); - closeCombo(); - }; + task.id, + ) + closeCombo() + } - // Display two fist users profile image - const assigneeImg1 = useMemo(() => task?.members[0]?.user?.imageUrl, [task]); - const assigneeImg2 = useMemo(() => task?.members[1]?.user?.imageUrl, [task]); + const setParent = useCallback( + async ( + parentTask: ITeamTask, + newTask: ITeamTask, + closeModal: () => void, + ): Promise => { + if (parentTask.issueType !== "Epic") return + + const childTask = cloneDeep(newTask) + + await updateTask( + { + ...childTask, + parentId: parentTask.id, + parent: parentTask, + }, + childTask.id, + ) + + closeModal() + }, + [task], + ) + + // Display two first users profile image + const assigneeImg1 = useMemo(() => task?.members[0]?.user?.imageUrl, [task]) + const assigneeImg2 = useMemo(() => task?.members[1]?.user?.imageUrl, [task]) return ( { - closeCombo(); - setEditMode(false); + closeCombo() + setEditMode(false) }} > { - !isScrolling && handleActiveTask(task); + !parentTasksFilter + ? !isScrolling && handleActiveTask(task) + : !isScrolling && setParent(task, childTask, onDismiss) }} // added it here because doesn't work when assigned to the parent style={{ - flexDirection: 'row', - justifyContent: 'space-between', - alignItems: 'center', - width: '60%' + flexDirection: "row", + justifyContent: "space-between", + alignItems: "center", + width: "60%", }} > - {`#${task.taskNumber}`} + {`#${task.taskNumber}`} @@ -75,136 +117,159 @@ const IndividualTask: FC = observer( { - !isScrolling && handleActiveTask(task); + !parentTasksFilter + ? !isScrolling && handleActiveTask(task) + : !isScrolling && setParent(task, childTask, onDismiss) }} // added it here because doesn't work when assigned to the parent style={{ - flexDirection: 'row', - width: '40%', - alignItems: 'center', + flexDirection: "row", + width: "40%", + alignItems: "center", zIndex: 1000, - justifyContent: 'space-between' + justifyContent: "space-between", }} > - + - + {assigneeImg1 ? ( - + ) : task.members[0] ? ( ) : null} {assigneeImg2 ? ( - + ) : task.members[1] ? ( ) : null} - {task.status === 'closed' ? ( - onReopenTask()} /> + {task.status === "closed" ? ( + onReopenTask()} + /> ) : ( setShowDel(true)}> )} {showDel && ( - + )} - ); - } -); + ) + }, +) const styles = StyleSheet.create({ container: { - alignItems: 'center', - borderTopColor: 'rgba(0, 0, 0, 0.06)', + alignItems: "center", + borderTopColor: "rgba(0, 0, 0, 0.06)", borderTopWidth: 1, - flexDirection: 'row', - justifyContent: 'space-between', + flexDirection: "row", + justifyContent: "space-between", paddingVertical: 12, - width: '100%', - zIndex: 1000 + width: "100%", + zIndex: 1000, }, prefix: { - color: '#FFFFFF', + color: "#FFFFFF", fontFamily: typography.fonts.PlusJakartaSans.light, - fontSize: 20 + fontSize: 20, }, statusContainer: { - alignItems: 'center', - backgroundColor: '#ECE8FC', - borderColor: 'transparent', + alignItems: "center", + backgroundColor: "#ECE8FC", + borderColor: "transparent", height: 27, marginRight: 6, paddingHorizontal: 7, width: 50, - zIndex: 1000 + zIndex: 1000, }, statusDisplay: { - flexDirection: 'row' + flexDirection: "row", }, taskTitle: { - color: '#282048', + color: "#282048", fontFamily: typography.fonts.PlusJakartaSans.semiBold, fontSize: 10, - width: '67%' + width: "67%", }, wrapBugIcon: { - alignItems: 'center', - backgroundColor: '#C24A4A', + alignItems: "center", + backgroundColor: "#C24A4A", borderRadius: 3, height: 20, - justifyContent: 'center', + justifyContent: "center", marginRight: 3, - width: 20 + width: 20, }, wrapTaskNumber: { - alignItems: 'center', - flexDirection: 'row' - } -}); + alignItems: "center", + flexDirection: "row", + }, +}) const $usersProfile: ImageStyle = { ...GS.roundedFull, backgroundColor: colors.background, width: spacing.extraLarge - spacing.tiny, height: spacing.extraLarge - spacing.tiny, - borderColor: '#fff', - borderWidth: 2 -}; + borderColor: "#fff", + borderWidth: 2, +} const $usersProfile2: ImageStyle = { ...GS.roundedFull, backgroundColor: colors.background, width: spacing.extraLarge - spacing.tiny, height: spacing.extraLarge - spacing.tiny, - borderColor: '#fff', + borderColor: "#fff", borderWidth: 2, - position: 'absolute', - left: -15 -}; + position: "absolute", + left: -15, +} -export default IndividualTask; +export default IndividualTask diff --git a/apps/mobile/app/screens/Authenticated/TimerScreen/components/TimerTaskSection.tsx b/apps/mobile/app/screens/Authenticated/TimerScreen/components/TimerTaskSection.tsx index 9fee67bb1..7c7614c4b 100644 --- a/apps/mobile/app/screens/Authenticated/TimerScreen/components/TimerTaskSection.tsx +++ b/apps/mobile/app/screens/Authenticated/TimerScreen/components/TimerTaskSection.tsx @@ -1,6 +1,6 @@ /* eslint-disable react-native/no-color-literals */ /* eslint-disable react-native/no-inline-styles */ -import React, { useCallback, useEffect, useRef, useState } from 'react'; +import React, { useCallback, useEffect, useRef, useState } from "react" import { View, StyleSheet, @@ -9,29 +9,29 @@ import { ViewStyle, TouchableWithoutFeedback, Dimensions, - Pressable -} from 'react-native'; -import { ActivityIndicator } from 'react-native-paper'; -import { GLOBAL_STYLE as GS } from '../../../../../assets/ts/styles'; -import ComboBox from './ComboBox'; -import EstimateTime from './EstimateTime'; -import { Feather } from '@expo/vector-icons'; -import { observer } from 'mobx-react-lite'; -import TaskPriorities from '../../../../components/TaskPriority'; + Pressable, +} from "react-native" +import { ActivityIndicator } from "react-native-paper" +import { GLOBAL_STYLE as GS } from "../../../../../assets/ts/styles" +import ComboBox from "./ComboBox" +import EstimateTime from "./EstimateTime" +import { Feather } from "@expo/vector-icons" +import { observer } from "mobx-react-lite" +import TaskPriorities from "../../../../components/TaskPriority" // import TaskLabel from "../../../../components/TaskLabel" -import { typography, useAppTheme } from '../../../../theme'; -import { translate } from '../../../../i18n'; -import TaskStatus from '../../../../components/TaskStatus'; -import TimerCard from '../../../../components/TimerCard'; -import TaskSize from '../../../../components/TaskSize'; -import { RTuseTaskInput } from '../../../../services/hooks/features/useTaskInput'; -import TaskLabels from '../../../../components/TaskLabels'; -import IssuesModal from '../../../../components/IssuesModal'; -import { useStores } from '../../../../models'; +import { typography, useAppTheme } from "../../../../theme" +import { translate } from "../../../../i18n" +import TaskStatus from "../../../../components/TaskStatus" +import TimerCard from "../../../../components/TimerCard" +import TaskSize from "../../../../components/TaskSize" +import { RTuseTaskInput } from "../../../../services/hooks/features/useTaskInput" +import TaskLabels from "../../../../components/TaskLabels" +import IssuesModal from "../../../../components/IssuesModal" +import { useStores } from "../../../../models" const TimerTaskSection = observer( ({ taskInput, outsideClick }: { taskInput: RTuseTaskInput; outsideClick: () => unknown }) => { - const { colors } = useAppTheme(); + const { colors } = useAppTheme() const { setEditMode, setQuery, @@ -40,32 +40,32 @@ const TimerTaskSection = observer( isModalOpen, hasCreateForm, handleTaskCreation, - createLoading - } = taskInput; + createLoading, + } = taskInput - const [combxShow, setCombxShow] = useState(false); - const inputRef = useRef(null); + const [combxShow, setCombxShow] = useState(false) + const inputRef = useRef(null) const { - TimerStore: { localTimerStatus } - } = useStores(); + TimerStore: { localTimerStatus }, + } = useStores() const closeCombox = useCallback(() => { - setCombxShow(false); - }, [setCombxShow]); + setCombxShow(false) + }, [setCombxShow]) useEffect(() => { if (isModalOpen || editMode) { - setCombxShow(true); + setCombxShow(true) } else { - setCombxShow(false); + setCombxShow(false) } - }, [isModalOpen, editMode]); + }, [isModalOpen, editMode]) useEffect(() => { if (!editMode) { - inputRef.current.blur(); + inputRef.current.blur() } - }, [editMode]); + }, [editMode]) return ( outsideClick()}> @@ -74,17 +74,17 @@ const TimerTaskSection = observer( style={[ styles.wrapInput, { - flexDirection: 'row', - alignItems: 'center', + flexDirection: "row", + alignItems: "center", borderColor: colors.border, - backgroundColor: colors.background - } + backgroundColor: colors.background, + }, ]} > - {!editMode && activeTask ? `#${activeTask.taskNumber} ` : ''} + {!editMode && activeTask ? `#${activeTask.taskNumber} ` : ""} { - handleTaskCreation(); - setEditMode(false); + handleTaskCreation() + setEditMode(false) }} > ) : null} - {createLoading ? : null} + {createLoading ? ( + + ) : null} {combxShow ? ( - + closeCombox()} + setEditMode={setEditMode} + tasksHandler={taskInput} + /> ) : ( - {translate('myWorkScreen.estimateLabel')} :{' '} + {translate("myWorkScreen.estimateLabel")} :{" "} @@ -158,23 +164,23 @@ const TimerTaskSection = observer( task={activeTask} containerStyle={{ ...styles.sizeContainer, - borderColor: colors.border + borderColor: colors.border, }} /> @@ -182,7 +188,7 @@ const TimerTaskSection = observer( task={activeTask} containerStyle={{ ...styles.sizeContainer, - borderColor: colors.border + borderColor: colors.border, }} /> @@ -190,9 +196,9 @@ const TimerTaskSection = observer( task={activeTask} containerStyle={{ ...styles.sizeContainer, - width: '100%', + width: "100%", borderColor: colors.border, - marginVertical: 20 + marginVertical: 20, }} /> @@ -200,12 +206,12 @@ const TimerTaskSection = observer( )} - ); - } -); -export default TimerTaskSection; + ) + }, +) +export default TimerTaskSection -const width = Dimensions.get('window').width; +const width = Dimensions.get("window").width const $timerSection: ViewStyle = { marginTop: 20, @@ -214,103 +220,103 @@ const $timerSection: ViewStyle = { borderRadius: 16, ...GS.noBorder, borderWidth: 1, - shadowColor: '#000', + shadowColor: "#000", shadowOffset: { width: 0, - height: 14 + height: 14, }, shadowOpacity: 0.1, shadowRadius: 44, - elevation: 8 -}; + elevation: 8, +} const styles = StyleSheet.create({ container: {}, dashed: { - borderBottomColor: '#fff', - borderBottomWidth: 10 + borderBottomColor: "#fff", + borderBottomWidth: 10, }, estimate: { - alignSelf: 'flex-end', - color: '#9490A0', + alignSelf: "flex-end", + color: "#9490A0", fontSize: 12, - fontWeight: '600', - marginBottom: 10 + fontWeight: "600", + marginBottom: 10, }, horizontal: { - flexDirection: 'row', - justifyContent: 'center', - marginBottom: 20 + flexDirection: "row", + justifyContent: "center", + marginBottom: 20, }, horizontalInput: { - alignItems: 'flex-end', - flexDirection: 'row' + alignItems: "flex-end", + flexDirection: "row", }, loading: { - right: 10 + right: 10, }, mainContainer: { - backgroundColor: '#fff', + backgroundColor: "#fff", borderRadius: 25, paddingTop: 30, padding: 20, ...GS.noBorder, borderWidth: 1, elevation: 5, - shadowColor: '#1B005D0D', + shadowColor: "#1B005D0D", shadowOffset: { width: 10, height: 10.5 }, shadowOpacity: 1, - shadowRadius: 15 + shadowRadius: 15, }, sizeContainer: { - alignItems: 'center', - borderColor: 'rgba(255, 255, 255, 0.13)', + alignItems: "center", + borderColor: "rgba(255, 255, 255, 0.13)", borderWidth: 1, height: 32, paddingHorizontal: 9, - width: width / 2.7 + width: width / 2.7, }, taskNumberStyle: { - color: '#7B8089', + color: "#7B8089", fontFamily: typography.primary.semiBold, fontSize: 14, - marginLeft: 5 + marginLeft: 5, }, textInput: { - backgroundColor: '#fff', + backgroundColor: "#fff", borderRadius: 10, - color: 'rgba(40, 32, 72, 0.4)', + color: "rgba(40, 32, 72, 0.4)", fontFamily: typography.fonts.PlusJakartaSans.semiBold, fontSize: 12, height: 43, paddingHorizontal: 6, paddingVertical: 13, - width: '80%' + width: "80%", }, textInputOne: { - height: 30 + height: 30, }, working: { - color: '#9490A0', - fontWeight: '600', - marginBottom: 10 + color: "#9490A0", + fontWeight: "600", + marginBottom: 10, }, wrapBugIcon: { - alignItems: 'center', - backgroundColor: '#C24A4A', + alignItems: "center", + backgroundColor: "#C24A4A", borderRadius: 3, height: 20, - justifyContent: 'center', - width: 20 + justifyContent: "center", + width: 20, }, wrapInput: { - backgroundColor: '#fff', - borderColor: 'rgba(0, 0, 0, 0.1)', + backgroundColor: "#fff", + borderColor: "rgba(0, 0, 0, 0.1)", borderRadius: 10, borderWidth: 1, height: 45, paddingHorizontal: 16, paddingVertical: 2, - width: '100%' - } -}); + width: "100%", + }, +}) diff --git a/apps/mobile/app/services/client/requests/auth.ts b/apps/mobile/app/services/client/requests/auth.ts index 915946b47..a2709aaf3 100644 --- a/apps/mobile/app/services/client/requests/auth.ts +++ b/apps/mobile/app/services/client/requests/auth.ts @@ -4,136 +4,140 @@ import { IRegisterDataRequest, ISuccessResponse, ISignInResponse, - ILoginResponse -} from '../../interfaces/IAuthentication'; -import { IUser } from '../../interfaces/IUserData'; -import { serverFetch } from '../fetch'; + ILoginResponse, +} from "../../interfaces/IAuthentication" +import { IUser } from "../../interfaces/IUserData" +import { serverFetch } from "../fetch" const registerDefaultValue = { - appName: 'Ever Teams', - appSignature: 'Ever Team', - appLogo: 'https://app.ever.team/assets/gauzy-team.png', - appLink: 'https://ever.team/', - appEmailConfirmationUrl: 'https://app.gauzy.co/#/auth/confirm-email' -}; + appName: "Ever Teams", + appSignature: "Ever Team", + appLogo: "https://app.ever.team/assets/ever-teams.png", + appLink: "https://ever.team/", + appEmailConfirmationUrl: "https://app.gauzy.co/#/auth/confirm-email", +} export const registerUserRequest = (data: IRegisterDataRequest) => { const body = { ...data, - ...registerDefaultValue - }; + ...registerDefaultValue, + } return serverFetch({ - path: '/auth/register', - method: 'POST', - body - }); -}; + path: "/auth/register", + method: "POST", + body, + }) +} export const loginUserRequest = (email: string, password: string) => { return serverFetch({ - path: '/auth/login', - method: 'POST', + path: "/auth/login", + method: "POST", body: { email, - password - } - }); -}; + password, + }, + }) +} export const whetherUserAuthenticatedRequest = (bearer_token: string) => { return serverFetch({ - path: '/user/authenticated', - method: 'GET', - bearer_token - }); -}; + path: "/user/authenticated", + method: "GET", + bearer_token, + }) +} type IUEmployeeParam = { - bearer_token: string; - relations?: string[]; -}; + bearer_token: string + relations?: string[] +} export const currentAuthenticatedUserRequest = ({ bearer_token, - relations = ['employee', 'role', 'tenant'] + relations = ["employee", "role", "tenant"], }: IUEmployeeParam) => { - const params = {} as { [x: string]: string }; + const params = {} as { [x: string]: string } relations.forEach((rl, i) => { - params[`relations[${i}]`] = rl; - }); + params[`relations[${i}]`] = rl + }) - const query = new URLSearchParams(params); + const query = new URLSearchParams(params) return serverFetch({ path: `/user/me?${query.toString()}`, - method: 'GET', - bearer_token - }); -}; + method: "GET", + bearer_token, + }) +} export const refreshTokenRequest = (refresh_token: string) => { return serverFetch<{ token: string }>({ - path: '/auth/refresh-token', - method: 'POST', + path: "/auth/refresh-token", + method: "POST", body: { - refresh_token - } - }); -}; + refresh_token, + }, + }) +} // auth/signin.email export function sendAuthCodeRequest(email: string) { - return serverFetch<{ status: number; message: string | 'ok' }>({ - path: '/auth/signin.email', - method: 'POST', - body: { email } - }); + return serverFetch<{ status: number; message: string | "ok" }>({ + path: "/auth/signin.email", + method: "POST", + body: { email }, + }) } // auth/signin.email/confirm Gives response with tenantId's export function verifyAuthCodeRequest(email: string, code: string) { return serverFetch({ - path: '/auth/signin.email/confirm?includeTeams=true', - method: 'POST', - body: { email, code } - }); + path: "/auth/signin.email/confirm?includeTeams=true", + method: "POST", + body: { email, code }, + }) } // auth/signin.workspace Need the email and the token from auth/signin.email/confirm export const signInWorkspaceRequest = (email: string, token: string) => { return serverFetch({ - path: '/auth/signin.workspace', - method: 'POST', - body: { email, token } - }); -}; + path: "/auth/signin.workspace", + method: "POST", + body: { email, token }, + }) +} export const verifyUserEmailByCodeRequest = (data: { - bearer_token: string; - code: string; - email: string; - tenantId: string; + bearer_token: string + code: string + email: string + tenantId: string }) => { - const { code, email, bearer_token, tenantId } = data; + const { code, email, bearer_token, tenantId } = data return serverFetch({ - path: '/auth/email/verify/code', - method: 'POST', + path: "/auth/email/verify/code", + method: "POST", body: { code, email, tenantId }, tenantId: data.tenantId, - bearer_token - }); -}; + bearer_token, + }) +} -export const resentVerifyUserLinkRequest = (data: { bearer_token: string; email: string; tenantId: string }) => { - const { email, bearer_token, tenantId } = data; +export const resentVerifyUserLinkRequest = (data: { + bearer_token: string + email: string + tenantId: string +}) => { + const { email, bearer_token, tenantId } = data return serverFetch({ - path: '/auth/email/verify/resend-link', - method: 'POST', + path: "/auth/email/verify/resend-link", + method: "POST", body: { email, tenantId }, tenantId: data.tenantId, - bearer_token - }); -}; + bearer_token, + }) +} diff --git a/apps/mobile/app/services/client/requests/tasks.ts b/apps/mobile/app/services/client/requests/tasks.ts index 06a0df130..33a837e4b 100644 --- a/apps/mobile/app/services/client/requests/tasks.ts +++ b/apps/mobile/app/services/client/requests/tasks.ts @@ -1,5 +1,5 @@ /* eslint-disable camelcase */ -import { DeleteReponse, PaginationResponse, CreateReponse } from "../../interfaces/IDataResponse" +import { DeleteResponse, PaginationResponse, CreateResponse } from "../../interfaces/IDataResponse" import { ICreateTask, ITeamTask } from "../../interfaces/ITask" import { serverFetch } from "../fetch" @@ -75,7 +75,7 @@ export function getTaskByIdRequest({ const query = new URLSearchParams(obj) - return serverFetch>({ + return serverFetch>({ path: `/tasks/${taskId}?${query.toString()}`, method: "GET", bearer_token, @@ -92,7 +92,7 @@ export function deleteTaskRequest({ taskId: string bearer_token: string }) { - return serverFetch({ + return serverFetch({ path: `/tasks/${taskId}?tenantId=${tenantId}`, method: "DELETE", bearer_token, @@ -138,7 +138,7 @@ export function deleteEmployeeFromTasksRequest({ organizationTeamId: string bearer_token: string }) { - return serverFetch({ + return serverFetch({ path: `/tasks/employee/${employeeId}?organizationTeamId=${organizationTeamId}`, method: "DELETE", bearer_token, diff --git a/apps/mobile/app/services/hooks/features/useTaskInput.ts b/apps/mobile/app/services/hooks/features/useTaskInput.ts index c95f5d73c..b5bf0f727 100644 --- a/apps/mobile/app/services/hooks/features/useTaskInput.ts +++ b/apps/mobile/app/services/hooks/features/useTaskInput.ts @@ -1,23 +1,23 @@ /* eslint-disable camelcase */ -import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; -import { ITeamTask } from '../../interfaces/ITask'; -import { useTeamTasks } from './useTeamTasks'; -import useAuthenticateUser from './useAuthentificateUser'; -import { useSyncRef } from '../useSyncRef'; -import { Nullable } from '../../interfaces/hooks'; -import { useModal } from '../useModal'; -import { useStores } from '../../../models'; - -export const h_filter = (status: string, filters: 'closed' | 'open') => { +import { useCallback, useEffect, useMemo, useRef, useState } from "react" +import { ITeamTask } from "../../interfaces/ITask" +import { useTeamTasks } from "./useTeamTasks" +import useAuthenticateUser from "./useAuthentificateUser" +import { useSyncRef } from "../useSyncRef" +import { Nullable } from "../../interfaces/hooks" +import { useModal } from "../useModal" +import { useStores } from "../../../models" + +export const h_filter = (status: string, filters: "closed" | "open") => { switch (filters) { - case 'open': - return status !== 'closed'; - case 'closed': - return status === 'closed'; + case "open": + return status !== "closed" + case "closed": + return status === "closed" default: - return true; + return true } -}; +} /** * It returns a bunch of variables and functions that are used to manage the task input @@ -28,132 +28,159 @@ export const h_filter = (status: string, filters: 'closed' | 'open') => { export function useTaskInput({ task, initEditMode, - tasks: customTasks + tasks: customTasks, }: { - tasks?: ITeamTask[]; - task?: Nullable; - initEditMode?: boolean; + tasks?: ITeamTask[] + task?: Nullable + initEditMode?: boolean } = {}) { const { - teamStore: { activeTeam } - } = useStores(); - const { isOpen: isModalOpen, openModal, closeModal } = useModal(); - const [closeableTask, setCloseableTaskTask] = useState(null); + teamStore: { activeTeam }, + } = useStores() + const { isOpen: isModalOpen, openModal, closeModal } = useModal() + const [closeableTask, setCloseableTaskTask] = useState(null) - const { teamTasks, createNewTask, activeTask, createLoading, tasksFetching, updateTask, setActiveTeamTask } = - useTeamTasks(); + const { + teamTasks, + createNewTask, + activeTask, + createLoading, + tasksFetching, + updateTask, + setActiveTeamTask, + } = useTeamTasks() - const { user } = useAuthenticateUser(); - const userRef = useSyncRef(user); + const { user } = useAuthenticateUser() + const userRef = useSyncRef(user) - const taskIssue = useRef(null); + const taskIssue = useRef(null) - const tasks = customTasks || (teamTasks as ITeamTask[]); + const tasks = customTasks || (teamTasks as ITeamTask[]) /** * If task has null value then consider it as value 😄 */ - const inputTask = task !== undefined ? task : activeTask; + const inputTask = task !== undefined ? task : activeTask - const [filter, setFilter] = useState<'closed' | 'open'>('open'); - const [editMode, setEditMode] = useState(initEditMode || false); + const [filter, setFilter] = useState<"closed" | "open">("open") + const [editMode, setEditMode] = useState(initEditMode || false) const handleOpenModal = useCallback( (concernedTask: ITeamTask) => { - setCloseableTaskTask(concernedTask); - openModal(); + setCloseableTaskTask(concernedTask) + openModal() }, - [setCloseableTaskTask] - ); + [setCloseableTaskTask], + ) const handleReopenTask = useCallback( async (concernedTask: ITeamTask) => { return updateTask( { ...concernedTask, - status: 'open' + status: "open", }, - concernedTask.id - ); + concernedTask.id, + ) }, - [updateTask] - ); + [updateTask], + ) - const [query, setQuery] = useState(''); + const [query, setQuery] = useState("") const filteredTasks = useMemo(() => { - return query.trim() === '' + return query.trim() === "" ? tasks.filter((task) => h_filter(task.status, filter)) : tasks.filter( (task) => task.title .trim() .toLowerCase() - .replace(/\s+/g, '') - .startsWith(query.toLowerCase().replace(/\s+/g, '')) && h_filter(task.status, filter) - ); - }, [query, filter, editMode, activeTeam]); + .replace(/\s+/g, "") + .startsWith(query.toLowerCase().replace(/\s+/g, "")) && + h_filter(task.status, filter), + ) + }, [query, filter, editMode, activeTeam]) const filteredTasks2 = useMemo(() => { - return query.trim() === '' + return query.trim() === "" ? tasks : tasks.filter((task) => { return task.title .trim() .toLowerCase() - .replace(/\s+/g, '') - .startsWith(query.toLowerCase().replace(/\s+/g, '')); - }); - }, [query]); + .replace(/\s+/g, "") + .startsWith(query.toLowerCase().replace(/\s+/g, "")) + }) + }, [query]) + + const filteredEpicTasks = useMemo(() => { + return query.trim() === "" + ? tasks.filter((task) => task.issueType === "Epic") + : tasks.filter((task) => { + return ( + task.title + .trim() + .toLowerCase() + .replace(/\s+/g, "") + .startsWith(query.toLowerCase().replace(/\s+/g, "")) && + task.issueType === "Epic" + ) + }) + }, [query]) - const hasCreateForm = filteredTasks2.length === 0 && query !== ''; + const hasCreateForm = filteredTasks2.length === 0 && query !== "" const handleTaskCreation = ({ autoAssignTaskAuth = true, - assignToUsers = [] + assignToUsers = [], }: { - autoActiveTask?: boolean; - autoAssignTaskAuth?: boolean; + autoActiveTask?: boolean + autoAssignTaskAuth?: boolean assignToUsers?: { - id: string; - }[]; + id: string + }[] } = {}) => { - if (query.trim().length < 2 || inputTask?.title === query.trim() || !userRef.current?.isEmailVerified) - return null; - - setEditMode(false); + if ( + query.trim().length < 2 || + inputTask?.title === query.trim() || + !userRef.current?.isEmailVerified + ) + return null + + setEditMode(false) return createNewTask( { taskName: query.trim(), - issueType: taskIssue.current || undefined + issueType: taskIssue.current || undefined, }, - !autoAssignTaskAuth ? assignToUsers : undefined - ); - }; + !autoAssignTaskAuth ? assignToUsers : undefined, + ) + } const updateTaskTitleHandler = useCallback((itask: ITeamTask, title: string) => { - if (!userRef.current?.isEmailVerified) return null; + if (!userRef.current?.isEmailVerified) return null return updateTask( { ...itask, - title + title, }, - itask.id - ); - }, []); + itask.id, + ) + }, []) const closedTaskCount = filteredTasks2.filter((f_task) => { - return f_task.status === 'closed'; - }).length; + return f_task.status === "closed" + }).length const openTaskCount = filteredTasks2.filter((f_task) => { - return f_task.status !== 'closed'; - }).length; + return f_task.status !== "closed" + }).length useEffect(() => { - taskIssue.current = null; - }, [hasCreateForm]); + taskIssue.current = null + }, [hasCreateForm]) return { closedTaskCount, @@ -161,6 +188,7 @@ export function useTaskInput({ hasCreateForm, handleTaskCreation, filteredTasks, + filteredEpicTasks, handleReopenTask, handleOpenModal, activeTask, @@ -179,8 +207,8 @@ export function useTaskInput({ taskIssue, user, userRef, - setActiveTeamTask - }; + setActiveTeamTask, + } } -export type RTuseTaskInput = ReturnType; +export type RTuseTaskInput = ReturnType diff --git a/apps/mobile/app/services/interfaces/IDataResponse.ts b/apps/mobile/app/services/interfaces/IDataResponse.ts index 67b7743ca..28f74a142 100644 --- a/apps/mobile/app/services/interfaces/IDataResponse.ts +++ b/apps/mobile/app/services/interfaces/IDataResponse.ts @@ -16,12 +16,12 @@ export type PaginationResponse = { total: number } -export type CreateReponse = { +export type CreateResponse = { data: T response: any } -export type DeleteReponse = { +export type DeleteResponse = { raw: string[] affected: number } diff --git a/apps/mobile/app/services/interfaces/ITask.ts b/apps/mobile/app/services/interfaces/ITask.ts index 3e27d07f5..200c4f7fb 100644 --- a/apps/mobile/app/services/interfaces/ITask.ts +++ b/apps/mobile/app/services/interfaces/ITask.ts @@ -1,142 +1,162 @@ -import { IEmployee } from './IEmployee'; -import { IOrganizationTeamList } from './IOrganizationTeam'; -import { ITaskLabelItem } from './ITaskLabel'; +import { IEmployee } from "./IEmployee" +import { IOrganizationTeamList } from "./IOrganizationTeam" +import { ITaskLabelItem } from "./ITaskLabel" export type ITeamTask = { - id: string; - createdAt: string; - updatedAt: string; - tenantId: string; - organizationId: string; - number: number; - prefix: string; - title: string; - description: string; - estimate: null | number; - totalWorkedTime?: number; - estimateDays?: number; - estimateHours?: number; - estimateMinutes?: number; - dueDate: string; - projectId: string; - creatorId: string; - members: IEmployee[]; - selectedTeam?: IOrganizationTeamList; - tags: ITaskLabelItem[]; - teams: SelectedTeam[]; - creator: Creator; - taskNumber: string; - label?: string; -} & ITaskStatusStack; + id: string + createdAt: string + updatedAt: string + tenantId: string + organizationId: string + number: number + prefix: string + title: string + description: string + estimate: null | number + totalWorkedTime?: number + estimateDays?: number + estimateHours?: number + estimateMinutes?: number + dueDate: string + projectId: string + public: boolean + resolvedAt?: string + creatorId: string + members: IEmployee[] + selectedTeam?: IOrganizationTeamList + tags: ITaskLabelItem[] + teams: SelectedTeam[] + linkedIssues?: LinkedTaskIssue[] + children?: Omit[] + creator: Creator + taskNumber: string + label?: string + parentId?: string + parent?: ITeamTask + rootEpic?: ITeamTask | null +} & ITaskStatusStack type SelectedTeam = Pick< IOrganizationTeamList, - 'id' | 'createdAt' | 'name' | 'organizationId' | 'tenantId' | 'updatedAt' | 'prefix' ->; + "id" | "createdAt" | "name" | "organizationId" | "tenantId" | "updatedAt" | "prefix" +> export interface Tag { - id: string; - createdAt: string; - updatedAt: string; - tenantId: string; - organizationId: string; - name: string; - description: string; - color: string; - isSystem: boolean; + id: string + createdAt: string + updatedAt: string + tenantId: string + organizationId: string + name: string + description: string + color: string + isSystem: boolean } interface Creator { - id: string; - createdAt: string; - updatedAt: string; - tenantId: string; - thirdPartyId: any; - firstName: string; - lastName: string; - email: string; - username: any; - hash: string; - refreshToken: any; - imageUrl: string; - preferredLanguage: string; - preferredComponentLayout: string; - isActive: boolean; - roleId: string; - name: string; - employeeId: any; + id: string + createdAt: string + updatedAt: string + tenantId: string + thirdPartyId: any + firstName: string + lastName: string + email: string + username: any + hash: string + refreshToken: any + imageUrl: string + preferredLanguage: string + preferredComponentLayout: string + isActive: boolean + roleId: string + name: string + employeeId: any } -export type ITaskPriority = 'Highest' | 'High' | 'Medium' | 'Low' | 'Lowest'; +export type LinkedTaskIssue = { + id: string + createdAt: string + updatedAt: string + tenantId: string + organizationId: string + action: number + taskFromId: string + taskToId: string + taskTo: Omit + taskFrom: Omit +} + +export type ITaskPriority = "Highest" | "High" | "Medium" | "Low" | "Lowest" -export type IVersionProperty = 'Version 1' | 'Version 2'; +export type IVersionProperty = "Version 1" | "Version 2" -export type IEpicProperty = string; +export type IEpicProperty = string -export type ITaskSize = 'X-Large' | 'Large' | 'Medium' | 'Small' | 'Tiny'; +export type ITaskSize = "X-Large" | "Large" | "Medium" | "Small" | "Tiny" -export type ITaskLabel = 'UI/UX' | 'Mobile' | 'WEB' | 'Tablet'; +export type ITaskLabel = "UI/UX" | "Mobile" | "WEB" | "Tablet" export type ITaskStatus = - | 'Blocked' - | 'Ready' - | 'Backlog' - | 'Todo' - | 'In Progress' - | 'Completed' - | 'Closed' - | 'In Review'; + | "Blocked" + | "Ready" + | "Backlog" + | "Todo" + | "In Progress" + | "Completed" + | "Closed" + | "In Review" -export type ITaskIssue = 'Bug' | 'Task' | 'Story' | 'Epic'; +export type ITaskIssue = "Bug" | "Task" | "Story" | "Epic" export type ITaskStatusField = - | 'status' - | 'size' - | 'priority' - | 'label' - | 'issue' - | 'version' - | 'epic' - | 'project' - | 'team' - | 'tags'; + | "status" + | "size" + | "priority" + | "label" + | "issue" + | "version" + | "epic" + | "project" + | "team" + | "tags" export type ITaskStatusStack = { - status: string; - size: string; - label: string; - priority: string; - issueType: string; - version: string; - epic: string; - project: string; // TODO: these types are not strings, but rather objects for team and project. To reimplement - team: string; // TODO: these types are not strings, but rather objects for team and project. To reimplement - tags: any; // TODO: these types are not strings, but rather array of objects for tags. To reimplement -}; + status: string + size: string + label: string + priority: string + issueType: string + version: string + epic: string + project: string // TODO: these types are not strings, but rather objects for team and project. To reimplement + team: string // TODO: these types are not strings, but rather objects for team and project. To reimplement + tags: any // TODO: these types are not strings, but rather array of objects for tags. To reimplement +} export interface ICreateTask { - title: string; - status: string; - priority?: string; - size?: string; - issueType?: string; - members?: { id: string; [x: string]: any }[]; - estimateDays?: number; - estimateHours?: string; - estimateMinutes?: string; - dueDate?: string; - description: string; - tags: ITaskLabelItem[]; - teams: { id: string }[]; - estimate: number; - organizationId: string; - tenantId: string; + title: string + status: string + priority?: string + size?: string + issueType?: string + members?: { id: string; [x: string]: any }[] + estimateDays?: number + estimateHours?: string + estimateMinutes?: string + dueDate?: string + description: string + tags: ITaskLabelItem[] + teams: { id: string }[] + estimate: number + organizationId: string + tenantId: string } export interface IParamsStatistic { - taskId: string; - bearer_token: string; - organizationId: string; - tenantId: string; - activeTask: boolean; + taskId: string + bearer_token: string + organizationId: string + tenantId: string + activeTask: boolean } diff --git a/apps/mobile/app/services/interfaces/interfaces/IDataResponse.ts b/apps/mobile/app/services/interfaces/interfaces/IDataResponse.ts index c9e7162f6..baa3753f7 100644 --- a/apps/mobile/app/services/interfaces/interfaces/IDataResponse.ts +++ b/apps/mobile/app/services/interfaces/interfaces/IDataResponse.ts @@ -1,22 +1,22 @@ interface IResponseMetadata { - status: ResStatusEnum; - message: string; - error: Error | null; + status: ResStatusEnum + message: string + error: Error | null } -export type IDataResponse = IResponseMetadata & T; +export type IDataResponse = IResponseMetadata & T export enum ResStatusEnum { - error = 'error', - success = 'success' + error = "error", + success = "success", } export type PaginationResponse = { - items: T[]; - total: number; -}; + items: T[] + total: number +} -export type DeleteReponse = { - raw: string[]; - affected: number; -}; +export type DeleteResponse = { + raw: string[] + affected: number +} diff --git a/apps/mobile/eas.json b/apps/mobile/eas.json index 0b0484cec..b7a2130fc 100644 --- a/apps/mobile/eas.json +++ b/apps/mobile/eas.json @@ -20,5 +20,14 @@ "production": { "channel": "production" } + }, + "submit":{ + "production":{ + "android":{ + "track":"internal", + "releaseStatus":"draft", + "changesNotSentForReview":false + } + } } } diff --git a/apps/mobile/ios/GauzyTeams/Supporting/Expo.plist b/apps/mobile/ios/GauzyTeams/Supporting/Expo.plist index e27e06cb5..d2b7d813a 100644 --- a/apps/mobile/ios/GauzyTeams/Supporting/Expo.plist +++ b/apps/mobile/ios/GauzyTeams/Supporting/Expo.plist @@ -11,6 +11,6 @@ EXUpdatesRuntimeVersion 1.0.0 EXUpdatesURL - https://u.expo.dev/9f38f768-16f6-4c47-b354-9745ebda1335 + https://u.expo.dev/2ff924e4-7a91-4b23-9db9-7453a8063bb0 - \ No newline at end of file + diff --git a/apps/web/.env b/apps/web/.env index 36e845f18..9bbae6394 100644 --- a/apps/web/.env +++ b/apps/web/.env @@ -28,7 +28,7 @@ NEXT_PUBLIC_DISABLE_AUTO_REFRESH=false # App Defaults APP_NAME="Ever Teams" APP_SIGNATURE="Ever Teams" -APP_LOGO_URL="https://app.ever.team/assets/gauzy-team.png" +APP_LOGO_URL="https://app.ever.team/assets/ever-teams.png" # Cookies NEXT_PUBLIC_COOKIE_DOMAINS=ever.team diff --git a/apps/web/.env.sample b/apps/web/.env.sample index f30d9ebd0..64988b851 100644 --- a/apps/web/.env.sample +++ b/apps/web/.env.sample @@ -25,7 +25,7 @@ SMTP_PASSWORD= # App Defaults APP_NAME='Ever Teams' APP_SIGNATURE='Ever Teams' -APP_LOGO_URL='https://app.ever.team/assets/gauzy-team.png' +APP_LOGO_URL='https://app.ever.team/assets/ever-teams.png' # Cookies NEXT_PUBLIC_COOKIE_DOMAINS=ever.team diff --git a/apps/web/app/constants.ts b/apps/web/app/constants.ts index 181e81743..66a737880 100644 --- a/apps/web/app/constants.ts +++ b/apps/web/app/constants.ts @@ -36,6 +36,7 @@ export const INVITE_CALLBACK_URL = process.env.INVITE_CALLBACK_URL; export const INVITE_CALLBACK_PATH = '/auth/passcode'; export const VERIFY_EMAIL_CALLBACK_URL = process.env.VERIFY_EMAIL_CALLBACK_URL; export const VERIFY_EMAIL_CALLBACK_PATH = '/verify-email'; +export const GA_MEASUREMENT_ID = process.env.NEXT_PUBLIC_GA_MEASUREMENT_ID; export const SMTP_FROM_ADDRESS = process.env.SMTP_FROM_ADDRESS || 'noreply@ever.team'; export const SMTP_HOST = process.env.SMTP_HOST || ''; @@ -47,7 +48,7 @@ export const DISABLE_AUTO_REFRESH = process.env.NEXT_PUBLIC_DISABLE_AUTO_REFRESH export const APP_NAME = process.env.APP_NAME || 'Ever Teams'; export const APP_SIGNATURE = process.env.APP_SIGNATURE || 'Ever Teams'; -export const APP_LOGO_URL = process.env.APP_LOGO_URL || 'https://app.ever.team/assets/gauzy-team.png'; +export const APP_LOGO_URL = process.env.APP_LOGO_URL || 'https://app.ever.team/assets/ever-teams.png'; export const APP_LINK = process.env.APP_LINK || 'https://ever.team/'; export const CHARACTER_LIMIT_TO_SHOW = 20; diff --git a/apps/web/app/hooks/features/useTaskStatus.ts b/apps/web/app/hooks/features/useTaskStatus.ts index 2e0239d9a..a11495330 100644 --- a/apps/web/app/hooks/features/useTaskStatus.ts +++ b/apps/web/app/hooks/features/useTaskStatus.ts @@ -1,7 +1,7 @@ import { ITaskStatusCreate } from '@app/interfaces'; import { createTaskStatusAPI, - getTaskstatusList, + getTaskStatusList, deleteTaskStatusAPI, editTaskStatusAPI } from '@app/services/client/api'; @@ -17,7 +17,7 @@ export function useTaskStatus() { const [user] = useRecoilState(userState); const activeTeamId = useRecoilValue(activeTeamIdState); - const { loading, queryCall } = useQuery(getTaskstatusList); + const { loading, queryCall } = useQuery(getTaskStatusList); const { loading: createTaskStatusLoading, queryCall: createQueryCall } = useQuery(createTaskStatusAPI); const { loading: deleteTaskStatusLoading, queryCall: deleteQueryCall } = useQuery(deleteTaskStatusAPI); const { loading: editTaskStatusLoading, queryCall: editQueryCall } = useQuery(editTaskStatusAPI); diff --git a/apps/web/app/hooks/features/useTaskVersion.ts b/apps/web/app/hooks/features/useTaskVersion.ts index 0616243df..5e5c1958c 100644 --- a/apps/web/app/hooks/features/useTaskVersion.ts +++ b/apps/web/app/hooks/features/useTaskVersion.ts @@ -2,7 +2,7 @@ import { ITaskVersionCreate } from '@app/interfaces'; import { createTaskVersionAPI, - getTaskversionList, + getTaskVersionList, deleteTaskVersionAPI, editTaskVersionAPI } from '@app/services/client/api'; @@ -19,7 +19,7 @@ export function useTaskVersion(onVersionCreated?: (version: ITaskVersionCreate) const [user] = useRecoilState(userState); const activeTeamId = useRecoilValue(activeTeamIdState); - const { loading, queryCall } = useQuery(getTaskversionList); + const { loading, queryCall } = useQuery(getTaskVersionList); const { loading: createTaskVersionLoading, queryCall: createQueryCall } = useQuery(createTaskVersionAPI); const { loading: deleteTaskVersionLoading, queryCall: deleteQueryCall } = useQuery(deleteTaskVersionAPI); const { loading: editTaskVersionLoading, queryCall: editQueryCall } = useQuery(editTaskVersionAPI); diff --git a/apps/web/app/interfaces/IDataResponse.ts b/apps/web/app/interfaces/IDataResponse.ts index 2acdaa852..90d3154dd 100644 --- a/apps/web/app/interfaces/IDataResponse.ts +++ b/apps/web/app/interfaces/IDataResponse.ts @@ -16,12 +16,12 @@ export type PaginationResponse = { total: number; }; -export type DeleteReponse = { +export type DeleteResponse = { raw: string[]; affected: number; }; -export type CreateReponse = { +export type CreateResponse = { data: T; response: any; }; diff --git a/apps/web/app/services/client/api/email-reset.ts b/apps/web/app/services/client/api/email-reset.ts index 4c02f0be8..94e53c0cb 100644 --- a/apps/web/app/services/client/api/email-reset.ts +++ b/apps/web/app/services/client/api/email-reset.ts @@ -1,11 +1,11 @@ -import { CreateReponse, ISuccessResponse } from '@app/interfaces'; +import { CreateResponse, ISuccessResponse } from '@app/interfaces'; import api from '../axios'; export function emailResetRequestAPI(email: string) { - return api.post>(`/email-reset/request-change-email`, { + return api.post>(`/email-reset/request-change-email`, { email }); } export function verifyChangeEmailRequestAPI(code: string) { - return api.post>(`/email-reset/verify-change-email`, { code }); + return api.post>(`/email-reset/verify-change-email`, { code }); } diff --git a/apps/web/app/services/client/api/index.ts b/apps/web/app/services/client/api/index.ts index 91a6eb620..24d25385a 100644 --- a/apps/web/app/services/client/api/index.ts +++ b/apps/web/app/services/client/api/index.ts @@ -7,7 +7,7 @@ export * from './email-reset'; export * from './languages'; -export * from './taskStatus'; +export * from './task-status'; export * from './task-version'; export * from './task-priorities'; export * from './task-sizes'; diff --git a/apps/web/app/services/client/api/integrations/github.ts b/apps/web/app/services/client/api/integrations/github.ts index 60617f389..8d2777bf0 100644 --- a/apps/web/app/services/client/api/integrations/github.ts +++ b/apps/web/app/services/client/api/integrations/github.ts @@ -1,4 +1,4 @@ -import { CreateReponse, IGithubMetadata, IGithubRepositories } from '@app/interfaces'; +import { CreateResponse, IGithubMetadata, IGithubRepositories } from '@app/interfaces'; import api from '../../axios'; // TODO @@ -12,10 +12,10 @@ export function oAuthEndpointAuthorizationAPI(body: any) { } export function getGithubIntegrationMetadataAPI(integrationId: string) { - return api.get>(`/integration/github/metadata?integrationId=${integrationId}`); + return api.get>(`/integration/github/metadata?integrationId=${integrationId}`); } export function getGithubIntegrationRepositoriesAPI(integrationId: string) { - return api.get>( + return api.get>( `/integration/github/repositories?integrationId=${integrationId}` ); } diff --git a/apps/web/app/services/client/api/integrations/index.ts b/apps/web/app/services/client/api/integrations/index.ts index e0109dfd8..be3eaf20c 100644 --- a/apps/web/app/services/client/api/integrations/index.ts +++ b/apps/web/app/services/client/api/integrations/index.ts @@ -1,8 +1,8 @@ -import { CreateReponse, IIntegration } from '@app/interfaces'; +import { CreateResponse, IIntegration } from '@app/interfaces'; import api from '../../axios'; export function getIntegrationAPI(integrationTypeId: string, searchQuery = '') { - return api.get>( + return api.get>( `/integration?integrationTypeId=${integrationTypeId}&searchQuery=${searchQuery}` ); } diff --git a/apps/web/app/services/client/api/integrations/integration-tenant.ts b/apps/web/app/services/client/api/integrations/integration-tenant.ts index c8e8b1649..2efd0651b 100644 --- a/apps/web/app/services/client/api/integrations/integration-tenant.ts +++ b/apps/web/app/services/client/api/integrations/integration-tenant.ts @@ -1,8 +1,8 @@ -import { IIntegrationTenant, PaginationResponse, CreateReponse } from '@app/interfaces'; +import { IIntegrationTenant, PaginationResponse, CreateResponse } from '@app/interfaces'; import api from '../../axios'; export function getIntegrationTenantAPI(name: string) { - return api.get>>( + return api.get>>( `/integration-tenant/remember/state?name=${name}` ); } diff --git a/apps/web/app/services/client/api/integrations/types.ts b/apps/web/app/services/client/api/integrations/types.ts index 4ebc312c2..5532b170c 100644 --- a/apps/web/app/services/client/api/integrations/types.ts +++ b/apps/web/app/services/client/api/integrations/types.ts @@ -1,6 +1,6 @@ -import { CreateReponse, IIntegrationType } from '@app/interfaces'; +import { CreateResponse, IIntegrationType } from '@app/interfaces'; import api from '../../axios'; export function getIntegrationTypesAPI() { - return api.get>(`/integration/types`); + return api.get>(`/integration/types`); } diff --git a/apps/web/app/services/client/api/invite.ts b/apps/web/app/services/client/api/invite.ts index d603dbd73..7764b1c03 100644 --- a/apps/web/app/services/client/api/invite.ts +++ b/apps/web/app/services/client/api/invite.ts @@ -1,5 +1,5 @@ import { PaginationResponse } from '@app/interfaces/IDataResponse'; -import { IInvitation, IInviteRequest, IMyInvitations, MyInvitationActionEnum, CreateReponse } from '@app/interfaces'; +import { IInvitation, IInviteRequest, IMyInvitations, MyInvitationActionEnum, CreateResponse } from '@app/interfaces'; import api from '../axios'; export function inviteByEmailsAPI(data: IInviteRequest) { @@ -25,5 +25,5 @@ export function getMyInvitationsAPI() { } export function acceptRejectMyInvitationsAPI(invitationId: string, action: MyInvitationActionEnum) { - return api.put>(`/invite/${invitationId}?action=${action}`); + return api.put>(`/invite/${invitationId}?action=${action}`); } diff --git a/apps/web/app/services/client/api/issue-type.ts b/apps/web/app/services/client/api/issue-type.ts index 0e371ad00..709088ff2 100644 --- a/apps/web/app/services/client/api/issue-type.ts +++ b/apps/web/app/services/client/api/issue-type.ts @@ -1,8 +1,8 @@ -import { CreateReponse, DeleteReponse, IIssueTypesCreate } from '@app/interfaces'; +import { CreateResponse, DeleteResponse, IIssueTypesCreate } from '@app/interfaces'; import api from '../axios'; export function createIssueTypeAPI(data: IIssueTypesCreate, tenantId?: string) { - return api.post>('/issue-types', data, { + return api.post>('/issue-types', data, { headers: { 'Tenant-Id': tenantId } @@ -10,7 +10,7 @@ export function createIssueTypeAPI(data: IIssueTypesCreate, tenantId?: string) { } export function editIssueTypeAPI(id: string, data: IIssueTypesCreate, tenantId?: string) { - return api.put>(`/issue-types/${id}`, data, { + return api.put>(`/issue-types/${id}`, data, { headers: { 'Tenant-Id': tenantId } @@ -18,7 +18,7 @@ export function editIssueTypeAPI(id: string, data: IIssueTypesCreate, tenantId?: } export function deleteIssueTypeAPI(id: string) { - return api.delete(`/issue-types/${id}`); + return api.delete(`/issue-types/${id}`); } export function getIssueTypeList(tenantId: string, organizationId: string, activeTeamId: string | null) { diff --git a/apps/web/app/services/client/api/languages.ts b/apps/web/app/services/client/api/languages.ts index 1f708bd5a..e07c98399 100644 --- a/apps/web/app/services/client/api/languages.ts +++ b/apps/web/app/services/client/api/languages.ts @@ -1,6 +1,6 @@ -import { ILanguageItemList, CreateReponse, PaginationResponse } from '@app/interfaces'; +import { ILanguageItemList, CreateResponse, PaginationResponse } from '@app/interfaces'; import api from '../axios'; export function getLanguageListAPI(is_system: boolean) { - return api.get>>(`/languages?is_system=${is_system}`); + return api.get>>(`/languages?is_system=${is_system}`); } diff --git a/apps/web/app/services/client/api/organization-team-employee.ts b/apps/web/app/services/client/api/organization-team-employee.ts index 73965958f..e14328d1a 100644 --- a/apps/web/app/services/client/api/organization-team-employee.ts +++ b/apps/web/app/services/client/api/organization-team-employee.ts @@ -1,5 +1,5 @@ import { IOrganizationTeamEmployeeUpdate } from '@app/interfaces'; -import { CreateReponse } from '@app/interfaces/IDataResponse'; +import { CreateResponse } from '@app/interfaces/IDataResponse'; import { IOrganizationTeam } from '@app/interfaces/IOrganizationTeam'; import api from '../axios'; @@ -14,20 +14,20 @@ export function deleteOrganizationEmployeeTeamAPI({ organizationId: string; tenantId: string; }) { - return api.delete>( + return api.delete>( `/organization-team-employee/${id}?tenantId=${tenantId}&employeeId=${employeeId}&organizationId=${organizationId}` ); } export function updateOrganizationEmployeeTeamAPI(id: string, data: Partial) { - return api.put>(`/organization-team-employee/${id}`, data); + return api.put>(`/organization-team-employee/${id}`, data); } export function updateOrganizationTeamEmployeeActiveTaskAPI( id: string, data: Partial ) { - return api.put>( + return api.put>( `/organization-team-employee/${id}/active-task`, data ); diff --git a/apps/web/app/services/client/api/organization-team.ts b/apps/web/app/services/client/api/organization-team.ts index 0796fb08e..c50bf9ce5 100644 --- a/apps/web/app/services/client/api/organization-team.ts +++ b/apps/web/app/services/client/api/organization-team.ts @@ -1,4 +1,4 @@ -import { CreateReponse, DeleteReponse, ISuccessResponse, PaginationResponse } from '@app/interfaces/IDataResponse'; +import { CreateResponse, DeleteResponse, ISuccessResponse, PaginationResponse } from '@app/interfaces/IDataResponse'; import { IOrganizationTeamList, @@ -28,12 +28,12 @@ export function updateOrganizationTeamAPI(teamId: string, data: Partial>(`/organization-team/${id}`); + return api.delete>(`/organization-team/${id}`); } export function removeEmployeeOrganizationTeamAPI(employeeId: string) { return api.delete(`/organization-team/employee/${employeeId}`); } export function removeUserFromAllTeamAPI(userId: string) { - return api.delete>(`/organization-team/teams/${userId}`); + return api.delete>(`/organization-team/teams/${userId}`); } diff --git a/apps/web/app/services/client/api/public-organization-team.ts b/apps/web/app/services/client/api/public-organization-team.ts index 3f5e31103..cdef52033 100644 --- a/apps/web/app/services/client/api/public-organization-team.ts +++ b/apps/web/app/services/client/api/public-organization-team.ts @@ -1,14 +1,14 @@ -import { IOrganizationTeamList, CreateReponse, IDataResponse } from '@app/interfaces'; +import { IOrganizationTeamList, CreateResponse, IDataResponse } from '@app/interfaces'; import api from '../axios'; export function getPublicOrganizationTeamsAPI(profile_link: string, team_id: string) { - return api.get | IDataResponse>( + return api.get | IDataResponse>( `/public/team/${profile_link}/${team_id}?type=team` ); } export function getPublicOrganizationTeamsMiscDataAPI(profile_link: string, team_id: string) { - return api.get | IDataResponse>( + return api.get | IDataResponse>( `/public/team/${profile_link}/${team_id}?type=misc` ); } diff --git a/apps/web/app/services/client/api/request-to-join-team.ts b/apps/web/app/services/client/api/request-to-join-team.ts index b50e9329b..9a77927f4 100644 --- a/apps/web/app/services/client/api/request-to-join-team.ts +++ b/apps/web/app/services/client/api/request-to-join-team.ts @@ -4,18 +4,18 @@ import { IDataResponse, ISuccessResponse, IValidateRequestToJoin, - CreateReponse, + CreateResponse, PaginationResponse, IRequestToJoinActionEnum } from '@app/interfaces'; import api from '../axios'; export function requestToJoinAPI(data: IRequestToJoinCreate) { - return api.post>('/organization-team-join', data); + return api.post>('/organization-team-join', data); } export function validateRequestToJoinAPI(data: IValidateRequestToJoin) { - return api.post>>( + return api.post>>( '/organization-team-join/validate', data ); diff --git a/apps/web/app/services/client/api/task-labels.ts b/apps/web/app/services/client/api/task-labels.ts index 101a636a0..6aa94c6c6 100644 --- a/apps/web/app/services/client/api/task-labels.ts +++ b/apps/web/app/services/client/api/task-labels.ts @@ -1,8 +1,8 @@ -import { CreateReponse, DeleteReponse, ITaskLabelsCreate } from '@app/interfaces'; +import { CreateResponse, DeleteResponse, ITaskLabelsCreate } from '@app/interfaces'; import api from '../axios'; export function createTaskLabelsAPI(data: ITaskLabelsCreate, tenantId?: string) { - return api.post>('/tags', data, { + return api.post>('/tags', data, { headers: { 'Tenant-Id': tenantId } @@ -10,7 +10,7 @@ export function createTaskLabelsAPI(data: ITaskLabelsCreate, tenantId?: string) } export function editTaskLabelsAPI(id: string, data: ITaskLabelsCreate, tenantId?: string) { - return api.put>(`/tags/${id}`, data, { + return api.put>(`/tags/${id}`, data, { headers: { 'Tenant-Id': tenantId } @@ -18,7 +18,7 @@ export function editTaskLabelsAPI(id: string, data: ITaskLabelsCreate, tenantId? } export function deleteTaskLabelsAPI(id: string) { - return api.delete(`/tags/${id}`); + return api.delete(`/tags/${id}`); } export function getTaskLabelsList(tenantId: string, organizationId: string, activeTeamId: string | null) { diff --git a/apps/web/app/services/client/api/task-priorities.ts b/apps/web/app/services/client/api/task-priorities.ts index 31c8ea619..9c299cb4d 100644 --- a/apps/web/app/services/client/api/task-priorities.ts +++ b/apps/web/app/services/client/api/task-priorities.ts @@ -1,8 +1,8 @@ -import { CreateReponse, DeleteReponse, ITaskPrioritiesCreate } from '@app/interfaces'; +import { CreateResponse, DeleteResponse, ITaskPrioritiesCreate } from '@app/interfaces'; import api from '../axios'; export function createTaskPrioritiesAPI(data: ITaskPrioritiesCreate, tenantId?: string) { - return api.post>('/task-priorities', data, { + return api.post>('/task-priorities', data, { headers: { 'Tenant-Id': tenantId } @@ -10,7 +10,7 @@ export function createTaskPrioritiesAPI(data: ITaskPrioritiesCreate, tenantId?: } export function editTaskPrioritiesAPI(id: string, data: ITaskPrioritiesCreate, tenantId?: string) { - return api.put>(`/task-priorities/${id}`, data, { + return api.put>(`/task-priorities/${id}`, data, { headers: { 'Tenant-Id': tenantId } @@ -18,7 +18,7 @@ export function editTaskPrioritiesAPI(id: string, data: ITaskPrioritiesCreate, t } export function deleteTaskPrioritiesAPI(id: string) { - return api.delete(`/task-priorities/${id}`); + return api.delete(`/task-priorities/${id}`); } export function getTaskPrioritiesList(tenantId: string, organizationId: string, activeTeamId: string | null) { diff --git a/apps/web/app/services/client/api/task-related-issue-type.ts b/apps/web/app/services/client/api/task-related-issue-type.ts index aa5a7a8c9..155e6424d 100644 --- a/apps/web/app/services/client/api/task-related-issue-type.ts +++ b/apps/web/app/services/client/api/task-related-issue-type.ts @@ -1,8 +1,8 @@ -import { CreateReponse, DeleteReponse, ITaskRelatedIssueTypeCreate } from '@app/interfaces'; +import { CreateResponse, DeleteResponse, ITaskRelatedIssueTypeCreate } from '@app/interfaces'; import api from '../axios'; export function createTaskRelatedIssueTypeAPI(data: ITaskRelatedIssueTypeCreate, tenantId?: string) { - return api.post>('/task-related-issue-types', data, { + return api.post>('/task-related-issue-types', data, { headers: { 'Tenant-Id': tenantId } @@ -10,7 +10,7 @@ export function createTaskRelatedIssueTypeAPI(data: ITaskRelatedIssueTypeCreate, } export function editTaskRelatedIssueTypeAPI(id: string, data: ITaskRelatedIssueTypeCreate, tenantId?: string) { - return api.put>(`/task-related-issue-types/${id}`, data, { + return api.put>(`/task-related-issue-types/${id}`, data, { headers: { 'Tenant-Id': tenantId } @@ -18,7 +18,7 @@ export function editTaskRelatedIssueTypeAPI(id: string, data: ITaskRelatedIssueT } export function deleteTaskRelatedIssueTypeAPI(id: string) { - return api.delete(`/task-related-issue-types/${id}`); + return api.delete(`/task-related-issue-types/${id}`); } export function getTaskRelatedIssueTypeList(tenantId: string, organizationId: string, activeTeamId: string | null) { diff --git a/apps/web/app/services/client/api/task-sizes.ts b/apps/web/app/services/client/api/task-sizes.ts index 70e933abb..15d4a5425 100644 --- a/apps/web/app/services/client/api/task-sizes.ts +++ b/apps/web/app/services/client/api/task-sizes.ts @@ -1,8 +1,8 @@ -import { CreateReponse, DeleteReponse, ITaskSizesCreate } from '@app/interfaces'; +import { CreateResponse, DeleteResponse, ITaskSizesCreate } from '@app/interfaces'; import api from '../axios'; export function createTaskSizesAPI(data: ITaskSizesCreate, tenantId?: string) { - return api.post>('/task-sizes', data, { + return api.post>('/task-sizes', data, { headers: { 'Tenant-Id': tenantId } @@ -10,7 +10,7 @@ export function createTaskSizesAPI(data: ITaskSizesCreate, tenantId?: string) { } export function editTaskSizesAPI(id: string, data: ITaskSizesCreate, tenantId?: string) { - return api.put>(`/task-sizes/${id}`, data, { + return api.put>(`/task-sizes/${id}`, data, { headers: { 'Tenant-Id': tenantId } @@ -18,7 +18,7 @@ export function editTaskSizesAPI(id: string, data: ITaskSizesCreate, tenantId?: } export function deleteTaskSizesAPI(id: string) { - return api.delete(`/task-sizes/${id}`); + return api.delete(`/task-sizes/${id}`); } export function getTaskSizesList(tenantId: string, organizationId: string, activeTeamId: string | null) { diff --git a/apps/web/app/services/client/api/taskStatus.ts b/apps/web/app/services/client/api/task-status.ts similarity index 58% rename from apps/web/app/services/client/api/taskStatus.ts rename to apps/web/app/services/client/api/task-status.ts index 1d119227b..4dafd1542 100644 --- a/apps/web/app/services/client/api/taskStatus.ts +++ b/apps/web/app/services/client/api/task-status.ts @@ -1,8 +1,8 @@ -import { CreateReponse, DeleteReponse, ITaskStatusCreate } from '@app/interfaces'; +import { CreateResponse, DeleteResponse, ITaskStatusCreate } from '@app/interfaces'; import api from '../axios'; export function createTaskStatusAPI(data: ITaskStatusCreate, tenantId?: string) { - return api.post>('/task-statuses', data, { + return api.post>('/task-statuses', data, { headers: { 'Tenant-Id': tenantId } @@ -10,7 +10,7 @@ export function createTaskStatusAPI(data: ITaskStatusCreate, tenantId?: string) } export function editTaskStatusAPI(id: string, data: ITaskStatusCreate, tenantId?: string) { - return api.put>(`/task-statuses/${id}`, data, { + return api.put>(`/task-statuses/${id}`, data, { headers: { 'Tenant-Id': tenantId } @@ -18,9 +18,9 @@ export function editTaskStatusAPI(id: string, data: ITaskStatusCreate, tenantId? } export function deleteTaskStatusAPI(id: string) { - return api.delete(`/task-statuses/${id}`); + return api.delete(`/task-statuses/${id}`); } -export function getTaskstatusList(tenantId: string, organizationId: string, activeTeamId: string | null) { +export function getTaskStatusList(tenantId: string, organizationId: string, activeTeamId: string | null) { return api.get(`/task-statuses?tenantId=${tenantId}&organizationId=${organizationId}&activeTeamId=${activeTeamId}`); } diff --git a/apps/web/app/services/client/api/task-version.ts b/apps/web/app/services/client/api/task-version.ts index ba6afa9f3..34e67aad8 100644 --- a/apps/web/app/services/client/api/task-version.ts +++ b/apps/web/app/services/client/api/task-version.ts @@ -1,8 +1,8 @@ -import { CreateReponse, DeleteReponse, ITaskVersionCreate } from '@app/interfaces'; +import { CreateResponse, DeleteResponse, ITaskVersionCreate } from '@app/interfaces'; import api from '../axios'; export function createTaskVersionAPI(data: ITaskVersionCreate, tenantId?: string) { - return api.post>('/task-versions', data, { + return api.post>('/task-versions', data, { headers: { 'Tenant-Id': tenantId } @@ -10,7 +10,7 @@ export function createTaskVersionAPI(data: ITaskVersionCreate, tenantId?: string } export function editTaskVersionAPI(id: string, data: ITaskVersionCreate, tenantId?: string) { - return api.put>(`/task-versions/${id}`, data, { + return api.put>(`/task-versions/${id}`, data, { headers: { 'Tenant-Id': tenantId } @@ -18,9 +18,9 @@ export function editTaskVersionAPI(id: string, data: ITaskVersionCreate, tenantI } export function deleteTaskVersionAPI(id: string) { - return api.delete(`/task-versions/${id}`); + return api.delete(`/task-versions/${id}`); } -export function getTaskversionList(tenantId: string, organizationId: string, activeTeamId: string | null) { +export function getTaskVersionList(tenantId: string, organizationId: string, activeTeamId: string | null) { return api.get(`/task-versions?tenantId=${tenantId}&organizationId=${organizationId}&activeTeamId=${activeTeamId}`); } diff --git a/apps/web/app/services/client/api/tasks.ts b/apps/web/app/services/client/api/tasks.ts index 7af06fad8..d8fedf87d 100644 --- a/apps/web/app/services/client/api/tasks.ts +++ b/apps/web/app/services/client/api/tasks.ts @@ -1,10 +1,10 @@ -import { CreateReponse, DeleteReponse, PaginationResponse } from '@app/interfaces/IDataResponse'; +import { CreateResponse, DeleteResponse, PaginationResponse } from '@app/interfaces/IDataResponse'; import { ICreateTask, ITeamTask } from '@app/interfaces/ITask'; import { ITasksTimesheet } from '@app/interfaces/ITimer'; import api from '../axios'; export function getTasksByIdAPI(taskId: string) { - return api.get>(`/tasks/${taskId}`); + return api.get>(`/tasks/${taskId}`); } export function getTeamTasksAPI() { @@ -12,7 +12,7 @@ export function getTeamTasksAPI() { } export function deleteTaskAPI(taskId: string) { - return api.delete(`/tasks/${taskId}`); + return api.delete(`/tasks/${taskId}`); } export function updateTaskAPI(taskId: string, body: Partial) { @@ -40,5 +40,5 @@ export function allTaskTimesheetStatisticsAPI() { } export function deleteEmployeeFromTasksAPI(employeeId: string, organizationTeamId: string) { - return api.delete(`/tasks/employee/${employeeId}?organizationTeamId=${organizationTeamId}`); + return api.delete(`/tasks/employee/${employeeId}?organizationTeamId=${organizationTeamId}`); } diff --git a/apps/web/app/services/client/api/user.ts b/apps/web/app/services/client/api/user.ts index d8cd3b879..b878f67ba 100644 --- a/apps/web/app/services/client/api/user.ts +++ b/apps/web/app/services/client/api/user.ts @@ -1,10 +1,10 @@ -import { DeleteReponse } from '@app/interfaces'; +import { DeleteResponse } from '@app/interfaces'; import api from '../axios'; export function deleteUserAPI(id: string) { - return api.delete(`/user/${id}`); + return api.delete(`/user/${id}`); } export function resetUserAPI() { - return api.delete(`/user/reset`); + return api.delete(`/user/reset`); } diff --git a/apps/web/app/services/server/requests/tasks.ts b/apps/web/app/services/server/requests/tasks.ts index 5f7ab87e0..a255518fe 100644 --- a/apps/web/app/services/server/requests/tasks.ts +++ b/apps/web/app/services/server/requests/tasks.ts @@ -1,4 +1,4 @@ -import { CreateReponse, DeleteReponse, PaginationResponse, SingleDataResponse } from '@app/interfaces'; +import { CreateResponse, DeleteResponse, PaginationResponse, SingleDataResponse } from '@app/interfaces'; import { ICreateTask, ITeamTask } from '@app/interfaces/ITask'; import { serverFetch } from '../fetch'; import { IUser } from '@app/interfaces'; @@ -6,8 +6,8 @@ import { IUser } from '@app/interfaces'; export function getTeamTasksRequest({ tenantId, organizationId, - // TODO - // projectId, + projectId, + teamId, bearer_token, relations = [ 'tags', @@ -27,15 +27,16 @@ export function getTeamTasksRequest({ bearer_token: string; relations?: string[]; projectId?: string; + teamId: string; }) { const obj = { 'where[organizationId]': organizationId, 'where[tenantId]': tenantId, - // TODO - // 'where[projectId]': projectId, + 'where[projectId]': projectId, 'join[alias]': 'task', 'join[leftJoinAndSelect][members]': 'task.members', - 'join[leftJoinAndSelect][user]': 'members.user' + 'join[leftJoinAndSelect][user]': 'members.user', + 'where[teams][0]': teamId } as Record; relations.forEach((rl, i) => { @@ -91,7 +92,7 @@ export function getTaskByIdRequest({ const query = new URLSearchParams(obj); - return serverFetch>({ + return serverFetch>({ path: `/tasks/${taskId}?${query.toString()}`, method: 'GET', bearer_token, @@ -108,7 +109,7 @@ export function deleteTaskRequest({ taskId: string; bearer_token: string; }) { - return serverFetch({ + return serverFetch({ path: `/tasks/${taskId}?tenantId=${tenantId}`, method: 'DELETE', bearer_token, @@ -153,7 +154,7 @@ export function deleteEmployeeFromTasksRequest({ organizationTeamId: string; bearer_token: string; }) { - return serverFetch({ + return serverFetch({ path: `/tasks/employee/${employeeId}?organizationTeamId=${organizationTeamId}`, method: 'DELETE', bearer_token, diff --git a/apps/web/app/stores/team-tasks.ts b/apps/web/app/stores/team-tasks.ts index fcd722cee..cdcd41cdc 100644 --- a/apps/web/app/stores/team-tasks.ts +++ b/apps/web/app/stores/team-tasks.ts @@ -2,7 +2,6 @@ import moment from 'moment'; import { ITeamTask } from '@app/interfaces/ITask'; import { ITasksTimesheet } from '@app/interfaces/ITimer'; import { atom, selector } from 'recoil'; -import { activeTeamState } from './organization-team'; export const teamTasksState = atom({ key: 'teamTasksState', @@ -28,13 +27,10 @@ export const tasksByTeamState = selector({ key: 'tasksByTeamState', get: ({ get }) => { const tasks = get(teamTasksState); - const activeTeam = get(activeTeamState); return tasks - .filter((task) => { - return task.teams.some((tm) => { - return tm.id === activeTeam?.id; - }); + .filter(() => { + return true }) .sort((a, b) => moment(b.createdAt).diff(a.createdAt)); } diff --git a/apps/web/lib/features/team-members-card-view.tsx b/apps/web/lib/features/team-members-card-view.tsx index 56bf65055..c69fff7c7 100644 --- a/apps/web/lib/features/team-members-card-view.tsx +++ b/apps/web/lib/features/team-members-card-view.tsx @@ -1,4 +1,4 @@ -import { useAuthenticateUser, useModal, useOrganizationTeams, useTeamInvitations } from '@app/hooks'; +import { useAuthenticateUser, useModal, useTeamInvitations } from '@app/hooks'; import { Transition } from '@headlessui/react'; import { InviteFormModal } from './team/invite/invite-form-modal'; import { InvitedCard, InviteUserTeamCard } from './team/invite/user-invite-card'; @@ -9,13 +9,19 @@ interface Props { teamMembers: OT_Member[]; publicTeam: boolean; currentUser: OT_Member | undefined; + teamsFetching: boolean; } -const TeamMembersCardView: React.FC = ({ teamMembers: members, currentUser, publicTeam = false }) => { +const TeamMembersCardView: React.FC = ({ + teamMembers: members, + currentUser, + teamsFetching = false, + publicTeam = false +}) => { const { isTeamManager } = useAuthenticateUser(); - const { teamsFetching } = useOrganizationTeams(); + const { teamInvitations } = useTeamInvitations(); - const $teamsFetching = teamsFetching && members.length === 0; + return (
    {/* Current authenticated user members */} @@ -62,7 +68,7 @@ const TeamMembersCardView: React.FC = ({ teamMembers: members, currentUse {/* Loader skeleton */} m.employee.userId === user?.id); const $members = members.filter((member) => member.id !== currentUser?.id); + const $teamsFetching = teamsFetching && members.length === 0; let teamMembersView; @@ -27,7 +27,7 @@ export function TeamMembers({ publicTeam = false, kabanView = IssuesView.CARDS } case members.length === 0: teamMembersView = (
    -
    +
    @@ -38,12 +38,19 @@ export function TeamMembers({ publicTeam = false, kabanView = IssuesView.CARDS }
    ); break; - case kabanView === IssuesView.CARDS: + case kanbanView === IssuesView.CARDS: teamMembersView = ( - + <> + + ); break; - case kabanView === IssuesView.TABLE: + case kanbanView === IssuesView.TABLE: teamMembersView = ( + ); } return teamMembersView; diff --git a/apps/web/lib/i18n/en.ts b/apps/web/lib/i18n/en.ts index cd910228a..ec736c37e 100644 --- a/apps/web/lib/i18n/en.ts +++ b/apps/web/lib/i18n/en.ts @@ -366,7 +366,7 @@ export const en = { layout: { footer: { - RIGHTS_RESERVERD: 'All rights reserved.' + RIGHTS_RESERVED: 'All rights reserved.' } }, diff --git a/apps/web/lib/layout/footer.tsx b/apps/web/lib/layout/footer.tsx index eb3c2a6a4..e2a65f5c4 100644 --- a/apps/web/lib/layout/footer.tsx +++ b/apps/web/lib/layout/footer.tsx @@ -12,7 +12,7 @@ export function Footer({ className }: IClassName) { {t('layout.footer.COPY_RIGHT1', { date: new Date().getFullYear() })}{' '} {t('TITLE')} {t('layout.footer.BY')}{' '} {t('layout.footer.COPY_RIGHT4')}{' '} - {t('layout.footer.RIGHTS_RESERVERD')} + {t('layout.footer.RIGHTS_RESERVED')}

    diff --git a/apps/web/next.config.js b/apps/web/next.config.js index 4f1860fd8..b546ab890 100644 --- a/apps/web/next.config.js +++ b/apps/web/next.config.js @@ -3,6 +3,7 @@ const path = require('path'); // eslint-disable-next-line @typescript-eslint/no-var-requires /** @type {import('next').NextConfig} */ const nextConfig = { + output: process.env.NEXT_BUILD_OUTPUT_TYPE === 'standalone' ? 'standalone' : undefined, reactStrictMode: true, swcMinify: true, webpack: (config, { isServer }) => { diff --git a/apps/web/pages/_app.tsx b/apps/web/pages/_app.tsx index 5e517c059..0898e2479 100644 --- a/apps/web/pages/_app.tsx +++ b/apps/web/pages/_app.tsx @@ -1,8 +1,7 @@ /* eslint-disable no-mixed-spaces-and-tabs */ import 'react-loading-skeleton/dist/skeleton.css'; import '../styles/globals.css'; - -import { jitsuConfiguration } from '@app/constants'; +import { GA_MEASUREMENT_ID, jitsuConfiguration } from '@app/constants'; import { JitsuProvider } from '@jitsu/jitsu-react'; import { Analytics } from '@vercel/analytics/react'; import { AppState } from 'lib/app/init-state'; @@ -16,20 +15,27 @@ import { SkeletonTheme } from 'react-loading-skeleton'; import { RecoilRoot } from 'recoil'; import { JitsuAnalytics } from '../lib/components/services/jitsu-analytics'; import i18n from '../ni18n.config'; + const MyApp = ({ Component, pageProps }: AppProps) => { const isJitsuEnvsPresent = jitsuConfiguration.host && jitsuConfiguration.writeKey; return ( <> - + + {GA_MEASUREMENT_ID && ( + <> + + + )} + diff --git a/apps/web/pages/api/tasks/[id].ts b/apps/web/pages/api/tasks/[id].ts index b36f8fd87..87b475407 100644 --- a/apps/web/pages/api/tasks/[id].ts +++ b/apps/web/pages/api/tasks/[id].ts @@ -4,7 +4,7 @@ import { getTeamTasksRequest, updateTaskRequest, getTaskByIdRequest } from '@app import { NextApiRequest, NextApiResponse } from 'next'; export default async function handler(req: NextApiRequest, res: NextApiResponse) { - const { $res, user, tenantId, access_token, organizationId } = await authenticatedGuard(req, res); + const { $res, user, tenantId, access_token, organizationId, projectId, teamId} = await authenticatedGuard(req, res); if (!user) return $res(); const { id: taskId } = req.query; @@ -38,6 +38,8 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) const { data: tasks } = await getTeamTasksRequest({ tenantId, organizationId, + projectId, + teamId, bearer_token: access_token }); diff --git a/apps/web/pages/api/tasks/team.ts b/apps/web/pages/api/tasks/team.ts index 49bd43bc9..afd4ab9dc 100644 --- a/apps/web/pages/api/tasks/team.ts +++ b/apps/web/pages/api/tasks/team.ts @@ -4,7 +4,7 @@ import { createTaskRequest, getTeamTasksRequest } from '@app/services/server/req import { NextApiRequest, NextApiResponse } from 'next'; export default async function handler(req: NextApiRequest, res: NextApiResponse) { - const { $res, user, tenantId, organizationId, access_token, projectId } = await authenticatedGuard(req, res); + const { $res, user, tenantId, organizationId, access_token, projectId, teamId } = await authenticatedGuard(req, res); if (!user) return $res(); if (req.method === 'POST') { @@ -42,6 +42,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) tenantId, organizationId, projectId, + teamId, bearer_token: access_token }); diff --git a/apps/web/pages/index.tsx b/apps/web/pages/index.tsx index 73d058e71..78c95ed4b 100644 --- a/apps/web/pages/index.tsx +++ b/apps/web/pages/index.tsx @@ -79,7 +79,7 @@ function MainPage() {
    - {isTeamMember ? : } + {isTeamMember ? : } ); } diff --git a/apps/web/public/assets/ever-teams.png b/apps/web/public/assets/ever-teams.png new file mode 100644 index 000000000..5beaf9fea Binary files /dev/null and b/apps/web/public/assets/ever-teams.png differ diff --git a/apps/web/public/assets/gauzy-team.png b/apps/web/public/assets/gauzy-team.png deleted file mode 100644 index a939cac8f..000000000 Binary files a/apps/web/public/assets/gauzy-team.png and /dev/null differ diff --git a/apps/web/public/locales/ar/common.json b/apps/web/public/locales/ar/common.json index 4c627d09a..f89afdad2 100644 --- a/apps/web/public/locales/ar/common.json +++ b/apps/web/public/locales/ar/common.json @@ -494,11 +494,9 @@ "layout": { "footer": { - "RIGHTS_RESERVERD": "جميع الحقوق محفوظة.", + "RIGHTS_RESERVED": "جميع الحقوق محفوظة.", "COPY_RIGHT1": "© {{date}}-حاضر،", - "COPY_RIGHT2": "إيفر تيمز", - "COPY_RIGHT3": "فِرق جوزي", - + "COPY_RIGHT2": "Ever Teams", "COPY_RIGHT4": "إيفر ش.م.م.", "COMPANY_NAME": "إيفر ش.م.م.", "TERMS": "شروط الخدمة", diff --git a/apps/web/public/locales/bg/common.json b/apps/web/public/locales/bg/common.json index 96a7b498a..35cbd8ebe 100644 --- a/apps/web/public/locales/bg/common.json +++ b/apps/web/public/locales/bg/common.json @@ -499,10 +499,9 @@ "layout": { "footer": { - "RIGHTS_RESERVERD": "Всички права запазени.", + "RIGHTS_RESERVED": "Всички права запазени.", "COPY_RIGHT1": "© {{date}}-настояще,", "COPY_RIGHT2": "Ever Teams", - "COPY_RIGHT3": "Gauzy Teams", "COPY_RIGHT4": "Ever Co.", "COMPANY_NAME": "Ever Co. LTD.", "TERMS": "Общи условия", diff --git a/apps/web/public/locales/de/common.json b/apps/web/public/locales/de/common.json index 37c035cd9..05697e933 100644 --- a/apps/web/public/locales/de/common.json +++ b/apps/web/public/locales/de/common.json @@ -488,10 +488,9 @@ "layout": { "footer": { - "RIGHTS_RESERVERD": "Alle Rechte vorbehalten.", + "RIGHTS_RESERVED": "Alle Rechte vorbehalten.", "COPY_RIGHT1": "© {{date}}-Gegenwart,", "COPY_RIGHT2": "Ever Teams", - "COPY_RIGHT3": "Gauzy Teams", "COPY_RIGHT4": "Ever Co.", "COMPANY_NAME": "Ever Co. LTD.", "TERMS": "Nutzungsbedingungen", diff --git a/apps/web/public/locales/en/common.json b/apps/web/public/locales/en/common.json index 6f7cf20b4..657f3e9ea 100644 --- a/apps/web/public/locales/en/common.json +++ b/apps/web/public/locales/en/common.json @@ -489,10 +489,9 @@ "layout": { "footer": { - "RIGHTS_RESERVERD": "All rights reserved.", + "RIGHTS_RESERVED": "All rights reserved.", "COPY_RIGHT1": "© {{date}}-Present,", - "COPY_RIGHT2": "Ever Teams ", - "COPY_RIGHT3": "Gauzy Teams", + "COPY_RIGHT2": "Ever Teams", "COPY_RIGHT4": "Ever Co.", "COMPANY_NAME": "Ever Co. LTD.", "TERMS": "Terms of Service", diff --git a/apps/web/public/locales/es/common.json b/apps/web/public/locales/es/common.json index 1f3b2701d..50eedaa10 100644 --- a/apps/web/public/locales/es/common.json +++ b/apps/web/public/locales/es/common.json @@ -473,10 +473,9 @@ }, "layout": { "footer": { - "RIGHTS_RESERVERD": "Todos los derechos reservados.", + "RIGHTS_RESERVED": "Todos los derechos reservados.", "COPY_RIGHT1": "© {{date}}-Presente,", - "COPY_RIGHT2": "Equipos Siempre ", - "COPY_RIGHT3": "Equipos Gauzy", + "COPY_RIGHT2": "Ever Teams", "COPY_RIGHT4": "Ever Co.", "COMPANY_NAME": "Ever Co. LTD.", "TERMS": "Términos del servicio", diff --git a/apps/web/public/locales/fr/common.json b/apps/web/public/locales/fr/common.json index 5f77ba207..863e2384c 100644 --- a/apps/web/public/locales/fr/common.json +++ b/apps/web/public/locales/fr/common.json @@ -478,10 +478,9 @@ }, "layout": { "footer": { - "RIGHTS_RESERVERD": "Tous droits réservés.", + "RIGHTS_RESERVED": "Tous droits réservés.", "COPY_RIGHT1": "© {{date}} à nos jours,", - "COPY_RIGHT2": "Ever Teams ", - "COPY_RIGHT3": "Gauzy Teams", + "COPY_RIGHT2": "Ever Teams", "COPY_RIGHT4": "Ever Co.", "COMPANY_NAME": "Ever Co. LTD.", "TERMS": "Conditions d'utilisation", diff --git a/apps/web/public/locales/he/common.json b/apps/web/public/locales/he/common.json index 496695d38..62e81f413 100644 --- a/apps/web/public/locales/he/common.json +++ b/apps/web/public/locales/he/common.json @@ -484,10 +484,9 @@ "layout": { "footer": { - "RIGHTS_RESERVERD": "כל הזכויות שמורות.", + "RIGHTS_RESERVED": "כל הזכויות שמורות.", "COPY_RIGHT1": "© {{date}}-היום,", - "COPY_RIGHT2": "Ever צוותים", - "COPY_RIGHT3": "Gauzy צוותים ", + "COPY_RIGHT2": "Ever Teams", "COPY_RIGHT4": "Ever Co.", "COMPANY_NAME": "Ever Co. LTD.", "TERMS": "תנאי שימוש", diff --git a/apps/web/public/locales/it/common.json b/apps/web/public/locales/it/common.json index 4bf8b9183..ab85e8032 100644 --- a/apps/web/public/locales/it/common.json +++ b/apps/web/public/locales/it/common.json @@ -488,10 +488,9 @@ "layout": { "footer": { - "RIGHTS_RESERVERD": "All rights reserved.", + "RIGHTS_RESERVED": "All rights reserved.", "COPY_RIGHT1": "© {{date}}-Present,", - "COPY_RIGHT2": "Ever Teams ", - "COPY_RIGHT3": "Gauzy Teams", + "COPY_RIGHT2": "Ever Teams", "COPY_RIGHT4": "Ever Co.", "COMPANY_NAME": "Ever Co. LTD.", "TERMS": "Terms of Service", diff --git a/apps/web/public/locales/nl/common.json b/apps/web/public/locales/nl/common.json index bb66e16bf..cc5ce7e19 100644 --- a/apps/web/public/locales/nl/common.json +++ b/apps/web/public/locales/nl/common.json @@ -488,10 +488,9 @@ "layout": { "footer": { - "RIGHTS_RESERVERD": "Alle rechten voorbehouden.", + "RIGHTS_RESERVED": "Alle rechten voorbehouden.", "COPY_RIGHT1": "© {{date}}-Heden,", "COPY_RIGHT2": "Ever Teams", - "COPY_RIGHT3": "Gauzy Teams", "COPY_RIGHT4": "Ever Co.", "COMPANY_NAME": "Ever Co. LTD.", "TERMS": "Gebruiksvoorwaarden", diff --git a/apps/web/public/locales/pl/common.json b/apps/web/public/locales/pl/common.json index 4bf8b9183..ab85e8032 100644 --- a/apps/web/public/locales/pl/common.json +++ b/apps/web/public/locales/pl/common.json @@ -488,10 +488,9 @@ "layout": { "footer": { - "RIGHTS_RESERVERD": "All rights reserved.", + "RIGHTS_RESERVED": "All rights reserved.", "COPY_RIGHT1": "© {{date}}-Present,", - "COPY_RIGHT2": "Ever Teams ", - "COPY_RIGHT3": "Gauzy Teams", + "COPY_RIGHT2": "Ever Teams", "COPY_RIGHT4": "Ever Co.", "COMPANY_NAME": "Ever Co. LTD.", "TERMS": "Terms of Service", diff --git a/apps/web/public/locales/pt/common.json b/apps/web/public/locales/pt/common.json index 4bf8b9183..ab85e8032 100644 --- a/apps/web/public/locales/pt/common.json +++ b/apps/web/public/locales/pt/common.json @@ -488,10 +488,9 @@ "layout": { "footer": { - "RIGHTS_RESERVERD": "All rights reserved.", + "RIGHTS_RESERVED": "All rights reserved.", "COPY_RIGHT1": "© {{date}}-Present,", - "COPY_RIGHT2": "Ever Teams ", - "COPY_RIGHT3": "Gauzy Teams", + "COPY_RIGHT2": "Ever Teams", "COPY_RIGHT4": "Ever Co.", "COMPANY_NAME": "Ever Co. LTD.", "TERMS": "Terms of Service", diff --git a/apps/web/public/locales/ru/common.json b/apps/web/public/locales/ru/common.json index 4bf8b9183..ab85e8032 100644 --- a/apps/web/public/locales/ru/common.json +++ b/apps/web/public/locales/ru/common.json @@ -488,10 +488,9 @@ "layout": { "footer": { - "RIGHTS_RESERVERD": "All rights reserved.", + "RIGHTS_RESERVED": "All rights reserved.", "COPY_RIGHT1": "© {{date}}-Present,", - "COPY_RIGHT2": "Ever Teams ", - "COPY_RIGHT3": "Gauzy Teams", + "COPY_RIGHT2": "Ever Teams", "COPY_RIGHT4": "Ever Co.", "COMPANY_NAME": "Ever Co. LTD.", "TERMS": "Terms of Service", diff --git a/apps/web/public/locales/zh/common.json b/apps/web/public/locales/zh/common.json index c1ad6f42d..d04259013 100644 --- a/apps/web/public/locales/zh/common.json +++ b/apps/web/public/locales/zh/common.json @@ -465,10 +465,9 @@ "layout": { "footer": { - "RIGHTS_RESERVERD": "版权所有。", + "RIGHTS_RESERVED": "版权所有。", "COPY_RIGHT1": "© {{date}}-至今,", - "COPY_RIGHT2": "永恒团队", - "COPY_RIGHT3": "Gauzy团队", + "COPY_RIGHT2": "Ever Teams", "COPY_RIGHT4": "永恒公司", "COMPANY_NAME": "永恒有限公司", "TERMS": "服务条款", diff --git a/fly.toml b/fly.toml index 3ed1a5747..080eb74c9 100644 --- a/fly.toml +++ b/fly.toml @@ -9,6 +9,7 @@ kill_signal = "SIGINT" kill_timeout = "5m0s" [build] + image = "ghcr.io/ever-co/ever-teams-webapp:latest" [http_service] internal_port = 3000 diff --git a/netlify.toml b/netlify.toml new file mode 100644 index 000000000..a838114cb --- /dev/null +++ b/netlify.toml @@ -0,0 +1,5 @@ +[build] + base = "apps/web" + command = "yarn run build" + functions = "netlify/functions" + publish = ".next" diff --git a/railway.json b/railway.json new file mode 100644 index 000000000..f77c81405 --- /dev/null +++ b/railway.json @@ -0,0 +1,10 @@ +{ + "$schema": "https://railway.app/railway.schema.json", + "build": { + "builder": "DOCKERFILE" + }, + "deploy": { + "restartPolicyType": "ON_FAILURE", + "restartPolicyMaxRetries": 10 + } +} diff --git a/render.yaml b/render.yaml index 95cbc3114..9b71f90e4 100644 --- a/render.yaml +++ b/render.yaml @@ -44,7 +44,7 @@ services: - key: APP_SIGNATURE value: 'Ever Teams' - key: APP_LOGO_URL - value: 'https://app.ever.team/assets/gauzy-team.png' + value: 'https://app.ever.team/assets/ever-teams.png' - key: NEXT_PUBLIC_COOKIE_DOMAINS value: ever.team - key: NEXT_PUBLIC_BOARD_APP_DOMAIN diff --git a/yarn.lock b/yarn.lock index 4344273a0..322a4b395 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18820,9 +18820,9 @@ streamsearch@^1.1.0: integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg== streamx@^2.15.0: - version "2.15.1" - resolved "https://registry.yarnpkg.com/streamx/-/streamx-2.15.1.tgz#396ad286d8bc3eeef8f5cea3f029e81237c024c6" - integrity sha512-fQMzy2O/Q47rgwErk/eGeLu/roaFWV0jVsogDmrszM9uIw8L5OA+t+V93MgYlufNptfjmYR1tOMWhei/Eh7TQA== + version "2.15.2" + resolved "https://registry.yarnpkg.com/streamx/-/streamx-2.15.2.tgz#680eacebdc9c43ede7362c2e6695b34dd413c741" + integrity sha512-b62pAV/aeMjUoRN2C/9F0n+G8AfcJjNC0zw/ZmOHeFsIe4m4GzjVW9m6VHXVjk536NbdU9JRwKMJRfkc+zUFTg== dependencies: fast-fifo "^1.1.0" queue-tick "^1.0.1"