Browse Source

Merge branch 'master' of gitlab.com:jetup/rws/rws-appication

merge-requests/362/merge
Vitalik 2 years ago
parent
commit
ff1f39dc19
  1. 2
      ios/Podfile.lock
  2. 4
      ios/taskme.xcodeproj/project.pbxproj
  3. 2
      ios/taskme/Info.plist
  4. 8
      src/modules/account/components/fake-date-input-with-modal.component.tsx
  5. 6
      src/modules/account/validations/edit-account.validator.ts
  6. 60
      src/modules/home/screens/home.screen.tsx
  7. 16
      src/modules/root/hooks/use-app-socket-listener.hook.ts
  8. 18
      src/modules/tasks/components/actions-for-selected-items-row.component.tsx
  9. 4
      src/modules/tasks/components/tasks-list-with-header.component.tsx
  10. 29
      src/modules/tasks/config/selected-tasks-menu-options.config.ts
  11. 5
      src/modules/tasks/config/task-attachments-menu.config.ts
  12. 33
      src/modules/tasks/config/task-card-buttons.config.ts
  13. 13
      src/modules/tasks/config/task-menu-options.config.ts
  14. 85
      src/modules/tasks/helpers/index.ts
  15. 2
      src/modules/tasks/screens/filter-tasks-result.screen.tsx
  16. 16
      src/modules/tasks/screens/task-details.screen.tsx
  17. 24
      src/modules/tasks/smart-components/swipable-task-card.smart-component.tsx
  18. 10
      src/modules/tasks/smart-components/tasks-list-head.smart-component.tsx
  19. 2
      src/modules/tasks/smart-components/tasks-list.smart-component.tsx
  20. 1
      src/services/system/real-time.service.ts
  21. 3
      src/shared/events/index.ts
  22. 2
      src/shared/themes/dark/task-card.ts
  23. 4
      src/shared/themes/interfaces/task-card.interface.ts
  24. 6
      src/shared/themes/light/task-card.ts

2
ios/Podfile.lock

@ -749,4 +749,4 @@ SPEC CHECKSUMS: @@ -749,4 +749,4 @@ SPEC CHECKSUMS:
PODFILE CHECKSUM: d1cd3b32af0702e70a0ab15184e7f8457bfcc729
COCOAPODS: 1.11.3
COCOAPODS: 1.11.2

4
ios/taskme.xcodeproj/project.pbxproj

@ -863,7 +863,7 @@ @@ -863,7 +863,7 @@
COPY_PHASE_STRIP = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "";
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "arm64 ";
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
@ -928,7 +928,7 @@ @@ -928,7 +928,7 @@
COPY_PHASE_STRIP = YES;
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "";
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "arm64 ";
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;

2
ios/taskme/Info.plist

@ -50,7 +50,7 @@ @@ -50,7 +50,7 @@
<key>NSLocationWhenInUseUsageDescription</key>
<string></string>
<key>NSMicrophoneUsageDescription</key>
<string>Потрібно надати доступ для запису відео</string>
<string>Потрібно надати доступ для запису відео/аудіо</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Потрібно надати доступ до галереї</string>
<key>OneSignal_disable_badge_clearing</key>

8
src/modules/account/components/fake-date-input-with-modal.component.tsx

@ -2,7 +2,7 @@ import { $size, TouchableFakeInput } from '@/shared' @@ -2,7 +2,7 @@ import { $size, TouchableFakeInput } from '@/shared'
import { useTheme } from '@/shared/hooks/use-theme.hook'
import { PartialTheme } from '@/shared/themes/interfaces'
import moment from 'moment'
import 'moment/locale/uk'
import 'moment/locale/uk'
import React, { FC, useRef } from 'react'
import { StyleSheet, View, ViewStyle } from 'react-native'
import RBSheet from 'react-native-raw-bottom-sheet'
@ -22,8 +22,8 @@ export const FakeDateInputWithModal: FC<IProps> = ({ @@ -22,8 +22,8 @@ export const FakeDateInputWithModal: FC<IProps> = ({
error,
}) => {
const { styles } = useTheme(createStyles)
const dateToRender = moment(date).format('DD MMMM YYYY')
const dateToRender = date ? moment(date).format('DD MMMM YYYY') : ''
const sheetRef = useRef<RBSheet>()
const openModal = () => sheetRef.current.open()
@ -44,7 +44,7 @@ export const FakeDateInputWithModal: FC<IProps> = ({ @@ -44,7 +44,7 @@ export const FakeDateInputWithModal: FC<IProps> = ({
onChange(newDateOfBirthday)
hideModal()
}}
date={new Date(date)}
date={date ? new Date(date) : new Date()}
sheetRef={sheetRef}
title={'День народження'}
/>

6
src/modules/account/validations/edit-account.validator.ts

@ -48,14 +48,14 @@ const constraints = { @@ -48,14 +48,14 @@ const constraints = {
},
innerPhoneNumber: {
presence: presenceCost,
// presence: presenceCost,
length: {
minimum: 4,
message: '^Мінімальна довжина становить 4 цифри',
},
},
personalPhoneNumber: {
presence: presenceCost,
// presence: presenceCost,
length: {
minimum: 12,
message: '^Номер не валідний',
@ -68,7 +68,7 @@ const constraints = { @@ -68,7 +68,7 @@ const constraints = {
},
},
dateOfBirth: {
presence: true,
presence: presenceCost,
datetime: {
latest: moment.utc().subtract(18, 'years'),
message: '^Вам має бути не менше 18 років',

60
src/modules/home/screens/home.screen.tsx

@ -1,11 +1,4 @@ @@ -1,11 +1,4 @@
import React, {
FC,
useCallback,
useEffect,
useMemo,
useRef,
useState,
} from 'react'
import React, { FC, useCallback, useEffect, useMemo, useState } from 'react'
import { ScrollView, StyleSheet, TouchableOpacity, View } from 'react-native'
import {
$size,
@ -40,7 +33,8 @@ export const HomeScreen: FC<IProps> = ({ navigation }) => { @@ -40,7 +33,8 @@ export const HomeScreen: FC<IProps> = ({ navigation }) => {
const [searchValue, setValue] = useState<string>(null)
const [isOpenDrawer, setDrawer] = useState<boolean>(false)
const countsRef = useRef(defaultCountsState)
const [counts, setCounts] = useState(defaultCountsState)
const taskFilter = useTaskFilter({
onSubmit: () => {
setDrawer(false)
@ -65,39 +59,31 @@ export const HomeScreen: FC<IProps> = ({ navigation }) => { @@ -65,39 +59,31 @@ export const HomeScreen: FC<IProps> = ({ navigation }) => {
}, [])
useEffect(() => {
if (!searchValue) countsRef.current = defaultCountsState
if (!searchValue) setCounts(counts)
}, [searchValue])
const searchResult = useMemo(
() => getHomeSearchResult(countsRef.current, searchValue),
[
searchValue,
countsRef.current.tasks,
countsRef.current.executors,
countsRef.current.groups,
],
() => getHomeSearchResult(counts, searchValue),
[searchValue, counts],
)
const setTasksCount = useCallback(
count => {
countsRef.current.tasks = count
},
[countsRef.current],
)
const setExecutorsCount = useCallback(
count => {
countsRef.current.executors = count
},
[countsRef.current],
)
const setGroupsCount = useCallback(
count => {
countsRef.current.groups = count
},
[countsRef.current],
)
const setTasksCount = count =>
setCounts({
...counts,
tasks: count,
})
const setExecutorsCount = count =>
setCounts({
...counts,
executors: count,
})
const setGroupsCount = count =>
setCounts({
...counts,
groups: count,
})
const openDrawer = useCallback(() => {
setDrawer(true)

16
src/modules/root/hooks/use-app-socket-listener.hook.ts

@ -1,12 +1,22 @@ @@ -1,12 +1,22 @@
import { chatMessageManager } from '@/managers/chat-message.manager'
import { authService, taxonomiesService } from '@/services/domain'
import {
authService,
permissionsService,
taxonomiesService,
} from '@/services/domain'
import { SocketEvents, useSocketListener } from '@/shared'
export const useAppSocketListener = () => {
const onStopSession = async () => await authService.stopSession()
const onChangedUserPermissions = async () => {
console.log('permission changed')
await permissionsService.loadPermissionsForUsers()
}
const onNewTaxonomy = async (data: SocketEvents['taxonomy/new']) =>
await taxonomiesService.onNewTaxonomy(data)
// ********************************
// Після успішного збереження повідомлень, надісланих офлайн, на бекенді з затримкою кидається даний сокет сигнал
// Використовується для того, щоб замінити дані повідомлення в локальній бд на реальні повідомлення
@ -30,4 +40,6 @@ export const useAppSocketListener = () => { @@ -30,4 +40,6 @@ export const useAppSocketListener = () => {
useSocketListener('taxonomy/new', onNewTaxonomy, [])
useSocketListener('chat/new-message-offline', onNewMessageOffline, [])
useSocketListener('user/change-permissions', onChangedUserPermissions, [])
}

18
src/modules/tasks/components/actions-for-selected-items-row.component.tsx

@ -6,6 +6,7 @@ import { @@ -6,6 +6,7 @@ import {
ITaskActionPayload,
ITaskDetails,
ITaskPreview,
IUser,
RoundButton,
TaskStatus,
Txt,
@ -15,12 +16,17 @@ import { PartialTheme } from '@/shared/themes/interfaces' @@ -15,12 +16,17 @@ import { PartialTheme } from '@/shared/themes/interfaces'
import { View, StyleSheet, ViewStyle } from 'react-native'
import { ActionsIconsForSelected } from '../atoms'
import _ from 'lodash'
import { checkIsTaskActionPossibleByUser } from '../helpers'
interface IProps {
title: string
style?: ViewStyle
taskIds: (number | string)[]
tasks?: ITaskDetails[]
tasks?: ITaskPreview[]
user?: IUser
permissions?: {
[x: string]: string[]
}
dates: string[]
onPressActionIcon: (
action: FullTaskActions,
@ -47,6 +53,16 @@ export const ActionsForSelectedItemsRow: FC<IProps> = ({ @@ -47,6 +53,16 @@ export const ActionsForSelectedItemsRow: FC<IProps> = ({
if (_.isEmpty(tasks)) return result
tasks.forEach(it => {
const availableOptions = checkIsTaskActionPossibleByUser(
props.user,
it.authorId,
it.executor.id,
props.permissions,
)
if (!availableOptions.canDestroy) result.hasRemoved = true
if (!availableOptions.canUpdate) result.hasFinished = true
if (it.doneDate) result.hasFinished = true
if (it.status === TaskStatus.Deleted) {
result.hasRemoved = true

4
src/modules/tasks/components/tasks-list-with-header.component.tsx

@ -7,7 +7,6 @@ import { @@ -7,7 +7,6 @@ import {
} from '@/shared'
import { useTheme } from '@/shared/hooks/use-theme.hook'
import { PartialTheme } from '@/shared/themes/interfaces'
import { selectAccount } from '@/store/account'
import _ from 'lodash'
import React, { FC } from 'react'
import {
@ -17,7 +16,6 @@ import { @@ -17,7 +16,6 @@ import {
Text,
ActivityIndicator,
} from 'react-native'
import { useSelector } from 'react-redux'
import { TasksListHeader } from '../atoms'
import { createCardStyles, isOverdueCheck } from '../helpers'
import { SwipableTaskCard } from '../smart-components'
@ -60,6 +58,8 @@ export const TasksListWithHeader: FC<IProps> = ({ @@ -60,6 +58,8 @@ export const TasksListWithHeader: FC<IProps> = ({
<SwipableTaskCard
key={item.id.toString()}
id={item.id}
authorId={item.authorId}
executorId={item.executor.id}
isRead={item.isRead}
isFavorite={item.isFavorite}
hasComments={item?.hasComments}

29
src/modules/tasks/config/selected-tasks-menu-options.config.ts

@ -1,18 +1,28 @@ @@ -1,18 +1,28 @@
import {
appEvents,
EUserRole,
FullTaskActions,
ITaskActionPayload,
ITaskPreview,
IUser,
RouteKey,
TaskStatus,
} from '@/shared'
import _ from 'lodash'
import { checkIsTaskActionPossibleByUser } from '../helpers'
interface IMenuOption {
name: string
onPress: () => void
}
const getSummary = (tasks: ITaskPreview[]) => {
const getSummary = (
tasks: ITaskPreview[],
user: IUser,
permissions: {
[x: string]: string[]
},
) => {
const result = {
hasFinished: false,
hasRemoved: false,
@ -22,7 +32,18 @@ const getSummary = (tasks: ITaskPreview[]) => { @@ -22,7 +32,18 @@ const getSummary = (tasks: ITaskPreview[]) => {
if (_.isEmpty(tasks)) return result
tasks.forEach(it => {
const availableOptions = checkIsTaskActionPossibleByUser(
user,
it.authorId,
it.executor.id,
permissions,
)
if (!availableOptions.canDestroy) result.hasRemoved = true
if (!availableOptions.canUpdate) result.hasFinished = true
if (it.doneDate) result.hasFinished = true
if (it.status === TaskStatus.Deleted) {
result.hasRemoved = true
result.hasFinished = true
@ -38,6 +59,10 @@ const getSummary = (tasks: ITaskPreview[]) => { @@ -38,6 +59,10 @@ const getSummary = (tasks: ITaskPreview[]) => {
}
export const getSelectedTasksMenuOptions = (
user: IUser,
permissions: {
[x: string]: string[]
},
tasks: ITaskPreview[],
navigate: (key: RouteKey, params?: Record<any, any>) => void,
actions: {
@ -48,7 +73,7 @@ export const getSelectedTasksMenuOptions = ( @@ -48,7 +73,7 @@ export const getSelectedTasksMenuOptions = (
) => void
},
) => {
const summary = getSummary(tasks)
const summary = getSummary(tasks, user, permissions)
const result = []

5
src/modules/tasks/config/task-attachments-menu.config.ts

@ -1,8 +1,5 @@ @@ -1,8 +1,5 @@
import { TaskAttachmentsActionMode } from './../enum/task-attachments.enums'
import {
alertNotAllowedFiles,
checkTaskFiles,
} from '@/shared/helpers'
import { alertNotAllowedFiles, checkTaskFiles } from '@/shared/helpers'
import { mediaService } from '@/services/system'
import _ from 'lodash'
import { appEvents, IFile } from '@/shared'

33
src/modules/tasks/config/task-card-buttons.config.ts

@ -5,21 +5,33 @@ import { @@ -5,21 +5,33 @@ import {
ITaskActionPayload,
TaskStatus,
} from '@/shared'
import { getCurrentThemeType } from '@/shared/helpers'
export const getTaskCardButtons = (
id: number | string,
date: string,
isTaskFavorite: boolean,
isAccessibleAction: {
canUpdate: boolean
canDestroy: boolean
},
onPress: (action: FullTaskActions, payload: ITaskActionPayload) => void,
status: TaskStatus,
closeSwipeable,
) => {
const theme = getCurrentThemeType()
const deleteBtn = {
title: 'Видалити',
bgColor: getTheme().$deleteBtn,
txtColor: getTheme().$deleteText,
bgColor: !isAccessibleAction.canDestroy
? getTheme(theme).$unAccessibleBtn
: getTheme(theme).$deleteBtn,
txtColor: !isAccessibleAction.canDestroy
? getTheme(theme).$unAccessibleTxt
: getTheme(theme).$deleteText,
iconName: 'bin',
onPress: () => {
if (!isAccessibleAction.canDestroy) return
closeSwipeable()
appEvents.emit('openConfirmModal', {
title: 'Видалити задачу?',
@ -27,15 +39,15 @@ export const getTaskCardButtons = ( @@ -27,15 +39,15 @@ export const getTaskCardButtons = (
allowBtnAction: () => {
setTimeout(() => onPress(FullTaskActions.Destroy, {}), 300)
},
notAllowBtnAction: () => { },
notAllowBtnAction: () => {},
})
},
}
const result = [
{
title: 'Обрана',
bgColor: getTheme().$pinBtn,
txtColor: getTheme().$pinText,
bgColor: getTheme(theme).$pinBtn,
txtColor: getTheme(theme).$pinText,
iconName: 'vectorstart',
onPress: () => {
closeSwipeable()
@ -51,7 +63,7 @@ export const getTaskCardButtons = ( @@ -51,7 +63,7 @@ export const getTaskCardButtons = (
else onPress(FullTaskActions.AddFavorite, {})
}, 500)
},
notAllowBtnAction: () => { },
notAllowBtnAction: () => {},
})
},
},
@ -62,10 +74,15 @@ export const getTaskCardButtons = ( @@ -62,10 +74,15 @@ export const getTaskCardButtons = (
result.unshift(deleteBtn)
result.unshift({
title: 'Виконати',
bgColor: getTheme().$doneBtn,
txtColor: getTheme().$doneText,
bgColor: !isAccessibleAction.canUpdate
? getTheme(theme).$unAccessibleBtn
: getTheme(theme).$doneBtn,
txtColor: !isAccessibleAction.canUpdate
? getTheme(theme).$unAccessibleTxt
: getTheme(theme).$doneText,
iconName: 'checks-1',
onPress: () => {
if (!isAccessibleAction.canUpdate) return
closeSwipeable()
appEvents.emit('openFinishTasksModal', {
taskIds: [id],

13
src/modules/tasks/config/task-menu-options.config.ts

@ -71,6 +71,10 @@ const createMenuOptions = ( @@ -71,6 +71,10 @@ const createMenuOptions = (
export const getMenuOptions = (
task: ITaskPreview,
isAccessibleAction: {
canUpdate: boolean
canDestroy: boolean
},
navigate: (key: RouteKey, params?: Record<any, any>) => void,
onPressRemove: () => void,
onPressAction: (
@ -88,6 +92,15 @@ export const getMenuOptions = ( @@ -88,6 +92,15 @@ export const getMenuOptions = (
const commonOptions = [menuOptions.copy, menuOptions.print]
if (!isAccessibleAction.canDestroy) {
delete menuOptions.delete
delete menuOptions.change_executor
}
if (!isAccessibleAction.canUpdate) {
delete menuOptions.edit
delete menuOptions.done
}
const menuOptionsByTaskStatus: Record<TaskStatus, IMenuOption[]> = {
[TaskStatus.Active]: Object.values(menuOptions),
[TaskStatus.Deleted]: commonOptions,

85
src/modules/tasks/helpers/index.ts

@ -1,21 +1,32 @@ @@ -1,21 +1,32 @@
import { IFullTaskInfo, ITaskPreview, TaskEvent, TaskStatus } from '@/shared'
import {
EUserRole,
IFullTaskInfo,
ITaskPreview,
IUser,
TaskEvent,
TaskStatus,
} from '@/shared'
import _ from 'lodash'
import moment from 'moment'
export const taskStatuses = {
'active': 'Активні',
'finished': 'Виконані',
'deleted': 'Видалені'
active: 'Активні',
finished: 'Виконані',
deleted: 'Видалені',
}
export const checkIsTaskReadByUser = (
task: Pick<ITaskPreview & {events?: Record<string, TaskEvent[]>}, 'events'> | Pick<IFullTaskInfo & {events?: Record<string, TaskEvent[]>}, 'events'>,
task:
| Pick<
ITaskPreview & { events?: Record<string, TaskEvent[]> },
'events'
>
| Pick<
IFullTaskInfo & { events?: Record<string, TaskEvent[]> },
'events'
>,
userId: number,
) =>
_.some(
task?.events,
event => event[`${userId}`] === TaskEvent.Read,
)
) => _.some(task?.events, event => event[`${userId}`] === TaskEvent.Read)
export const isUserOwnTask = (
task: ITaskPreview | IFullTaskInfo,
@ -23,7 +34,7 @@ export const isUserOwnTask = ( @@ -23,7 +34,7 @@ export const isUserOwnTask = (
) => task?.executor?.id === userId
export const isOverdueCheck = (endDate: string, status: TaskStatus) =>
moment(new Date()).isAfter(endDate) && status === TaskStatus.Active
moment(new Date()).isAfter(endDate) && status === TaskStatus.Active
export const createCardStyles = (items: any[], index: number) => {
let styles: any
@ -38,8 +49,54 @@ export const createCardStyles = (items: any[], index: number) => { @@ -38,8 +49,54 @@ export const createCardStyles = (items: any[], index: number) => {
borderBottomWidth: 0,
}
if (items?.length === 1)
styles = { borderRadius: 20, borderBottomWidth: 0 }
if (items?.length === 1) styles = { borderRadius: 20, borderBottomWidth: 0 }
return styles
}
}
export const checkIsTaskActionPossibleByUser = (
user: IUser,
authorId: number,
executorId: number,
permissions?: {
[x: string]: string[]
},
) => {
const result = {
canUpdate: false,
canDestroy: false,
}
if (user.role === EUserRole.Admin) {
result.canDestroy = true
result.canUpdate = true
return result
}
if (user.id === authorId && user.id === executorId) {
result.canDestroy = true
result.canUpdate = true
return result
}
if (
permissions &&
permissions.user &&
!_.isEmpty(permissions.user[executorId]) &&
permissions.user[executorId].includes('update')
) {
result.canUpdate = true
}
if (
permissions &&
permissions.user &&
!_.isEmpty(permissions.user[executorId]) &&
permissions.user[executorId].includes('destroy')
)
result.canDestroy = true
return result
}

2
src/modules/tasks/screens/filter-tasks-result.screen.tsx

@ -95,6 +95,8 @@ export const FilterTasksResultScreen: FC<IProps> = ({ route, navigation }) => { @@ -95,6 +95,8 @@ export const FilterTasksResultScreen: FC<IProps> = ({ route, navigation }) => {
<SwipableTaskCard
key={item.id.toString()}
id={item.id}
authorId={item.authorId}
executorId={item.executor.id}
hasComments={item?.hasComments}
hasUnreadComments={item.hasUnreadComments}
isFavorite={item.isFavorite}

16
src/modules/tasks/screens/task-details.screen.tsx

@ -24,6 +24,10 @@ import { getMenuOptions, getTaskDetailsRows, getTaskTerms } from '../config' @@ -24,6 +24,10 @@ import { getMenuOptions, getTaskDetailsRows, getTaskTerms } from '../config'
import { TaskAttachmentsActionMode } from '../enum'
import { useReasons, useTaskActions, useTaskDetails } from '../hooks'
import { TaskAttachmentsCollapseSmart } from '../smart-components'
import { useSelector } from 'react-redux'
import { selectAccount } from '@/store/account'
import { checkIsTaskActionPossibleByUser } from '../helpers'
import { selectPermissionsForUsers } from '@/store/permissions'
interface IProps extends IRouteParams {
route: {
@ -40,6 +44,8 @@ export const TaskDetailsScreen: FC<IProps> = ({ @@ -40,6 +44,8 @@ export const TaskDetailsScreen: FC<IProps> = ({
const { styles, theme } = useTheme(createStyles)
const nav = useNav()
const { id, isLoading, taskDetails, reload } = useTaskDetails(params.taskId)
const account = useSelector(selectAccount)
const permissions = useSelector(selectPermissionsForUsers)
const {
activeReason,
@ -60,9 +66,17 @@ export const TaskDetailsScreen: FC<IProps> = ({ @@ -60,9 +66,17 @@ export const TaskDetailsScreen: FC<IProps> = ({
await handleDeleteTask(taskDetails as any, () => nav.goBack())
}
const isAccessibleAction = checkIsTaskActionPossibleByUser(
account,
taskDetails?.authorId,
taskDetails?.executorId,
permissions,
)
const openMenu = () => {
const menuOptions = getMenuOptions(
taskDetails as any,
isAccessibleAction,
nav.navigate,
deleteTask,
handlePressOneTaskAction,
@ -135,7 +149,7 @@ export const TaskDetailsScreen: FC<IProps> = ({ @@ -135,7 +149,7 @@ export const TaskDetailsScreen: FC<IProps> = ({
/>
<TaskAttachmentsCollapseSmart
taskId={taskDetails.id}
taskId={taskDetails?.id}
docs={taskDetails?.documents}
mode={TaskAttachmentsActionMode.DETAIL}
/>

24
src/modules/tasks/smart-components/swipable-task-card.smart-component.tsx

@ -6,17 +6,23 @@ import { @@ -6,17 +6,23 @@ import {
} from '@/shared'
import { useTheme } from '@/shared/hooks/use-theme.hook'
import { PartialTheme } from '@/shared/themes/interfaces'
import { useFocusEffect } from '@react-navigation/native'
import _ from 'lodash'
import React, { FC, useEffect, useMemo, useRef } from 'react'
import { StyleSheet, View } from 'react-native'
import { Swipeable } from 'react-native-gesture-handler'
import { TaskCard } from '../components'
import { getTaskCardButtons } from '../config'
import { useSelector } from 'react-redux'
import { selectAccount } from '@/store/account'
import { checkIsTaskActionPossibleByUser } from '../helpers'
import { selectPermissionsForUsers } from '@/store/permissions'
import { getCurrentThemeType } from '@/shared/helpers'
interface IProps {
id: number | string
userName?: string
authorId: number
executorId: number
imageUrl?: string
title?: string
date?: string
@ -43,24 +49,36 @@ interface IProps { @@ -43,24 +49,36 @@ interface IProps {
export const SwipableTaskCard: FC<IProps> = ({ onPress, ...props }) => {
const { styles, theme } = useTheme(createStyles)
const account = useSelector(selectAccount)
const permissions = useSelector(selectPermissionsForUsers)
const appTheme = getCurrentThemeType()
const isAccessible = checkIsTaskActionPossibleByUser(
account,
props.authorId,
props.executorId,
permissions,
)
const btnsConfig = getTaskCardButtons(
props.id,
props.startTaskDate,
props.isFavorite,
isAccessible,
props.onPressActionButton,
_.defaultTo(props.status, TaskStatus.Active),
() => swipableRef.current.close(),
)
props.isFinished ? btnsConfig.splice(1, 1) : null
// props.isFinished ? btnsConfig.splice(0, 1) : null
const btnsToRender = useMemo(
() =>
btnsConfig.map(item => (
<SquareButton key={props.id + item.iconName} {...item} />
)),
[props.id, props.isFavorite],
[props.id, props.isFavorite, permissions, appTheme],
)
const onLongPress = btnsConfig[btnsConfig.length - 1].onPress

10
src/modules/tasks/smart-components/tasks-list-head.smart-component.tsx

@ -17,6 +17,9 @@ import { StyleSheet, TouchableOpacity, View, ViewStyle } from 'react-native' @@ -17,6 +17,9 @@ import { StyleSheet, TouchableOpacity, View, ViewStyle } from 'react-native'
import { ActionsForSelectedItemsRow } from '../components'
import { getSelectedTasksMenuOptions } from '../config'
import { useTaskActions } from '../hooks'
import { useSelector } from 'react-redux'
import { selectAccount } from '@/store/account'
import { selectPermissionsForUsers } from '@/store/permissions'
interface TasksListHeadSmartProps {
selectedTasks: ITaskDetails[]
@ -46,6 +49,9 @@ export const TasksListHeadSmart: FC<TasksListHeadSmartProps> = ({ @@ -46,6 +49,9 @@ export const TasksListHeadSmart: FC<TasksListHeadSmartProps> = ({
const navigation: any = useNavigation()
const { styles, theme } = useTheme(createStyles)
const account = useSelector(selectAccount)
const permissions = useSelector(selectPermissionsForUsers)
const goBack = () => {
simpleDispatch(new UnselectAllUsers())
simpleDispatch(new UnselectExecutor())
@ -58,6 +64,8 @@ export const TasksListHeadSmart: FC<TasksListHeadSmartProps> = ({ @@ -58,6 +64,8 @@ export const TasksListHeadSmart: FC<TasksListHeadSmartProps> = ({
const openMenu = () => {
const menuOptions = getSelectedTasksMenuOptions(
account,
permissions,
selectedTasks,
navigation.navigate,
{
@ -113,6 +121,8 @@ export const TasksListHeadSmart: FC<TasksListHeadSmartProps> = ({ @@ -113,6 +121,8 @@ export const TasksListHeadSmart: FC<TasksListHeadSmartProps> = ({
}
tasks={selectedTasks}
taskIds={selectedTasks.map(it => it.id)}
user={account}
permissions={permissions}
dates={selectedTasks.map(it => it.startDate)}
onPressClear={onPressClear}
onPressRemove={handleDeleteTasks}

2
src/modules/tasks/smart-components/tasks-list.smart-component.tsx

@ -47,6 +47,8 @@ export const TasksListSmart = ({ @@ -47,6 +47,8 @@ export const TasksListSmart = ({
<SwipableTaskCard
key={index.toString()}
id={item.id}
authorId={item.authorId}
executorId={item.executor.id}
overdue={isOverdueCheck(item.endDate, item.status)}
isRead={item.isRead}
isFavorite={item.isFavorite}

1
src/services/system/real-time.service.ts

@ -101,6 +101,7 @@ export class SocketIo { @@ -101,6 +101,7 @@ export class SocketIo {
this._onSocketSendEvent('stopSessions')
this._onSocketSendEvent('push-notification')
this._onSocketSendEvent('version')
this._onSocketSendEvent('user/change-permissions')
this._on('error/join-user', async () => {
await authService.refreshSession()

3
src/shared/events/index.ts

@ -152,7 +152,7 @@ export type SocketEvents = { @@ -152,7 +152,7 @@ export type SocketEvents = {
'chat/unpin': { chatId: number }
'chat/unread': { chatId: number }
'task/new-comment': { taskId: number, commentId: number, userId: number }
'task/new-comment': { taskId: number; commentId: number; userId: number }
'task/update-comment': { comment: IComment }
'task/read-comments': { taskId: number; userId?: number }
'task/delete-comment': {
@ -181,6 +181,7 @@ export type SocketEvents = { @@ -181,6 +181,7 @@ export type SocketEvents = {
'user/disconnected': { userId: number; sessionType: string }
'user/deleted': { userId: number }
'user/new-user': { userId: number }
'user/change-permissions': any
'taxonomy/new': { id: number; type: TaxonomyTypes }
stopSessions: { sessionsIds: number[] }

2
src/shared/themes/dark/task-card.ts

@ -17,4 +17,6 @@ export const taskCardColors: TaskCardColors = { @@ -17,4 +17,6 @@ export const taskCardColors: TaskCardColors = {
$doneText: '#27771B',
$deleteBtn: '#E4B9B9',
$deleteText: '#870D0D',
$unAccessibleBtn: '#353535',
$unAccessibleTxt: '#1A1919',
}

4
src/shared/themes/interfaces/task-card.interface.ts

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
export interface TaskCardColors {
taskTitle : {
taskTitle: {
$primaryText: string
$secondaryText: string
}
@ -15,4 +15,6 @@ export interface TaskCardColors { @@ -15,4 +15,6 @@ export interface TaskCardColors {
$doneText: string
$deleteBtn: string
$deleteText: string
$unAccessibleBtn: string
$unAccessibleTxt: string
}

6
src/shared/themes/light/task-card.ts

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@
import { TaskCardColors } from '../interfaces/task-card.interface'
export const taskCardColors: TaskCardColors = {
taskTitle : {
taskTitle: {
$primaryText: '#3B3B3B',
$secondaryText: '#9E2743',
},
@ -9,7 +9,7 @@ export const taskCardColors: TaskCardColors = { @@ -9,7 +9,7 @@ export const taskCardColors: TaskCardColors = {
$indicatorBg: '#9E2743',
},
selectedItems: {
$selectedText: '#C6C6C6'
$selectedText: '#C6C6C6',
},
$pinBtn: '#FFDF6D',
$pinText: '#B78F00',
@ -17,4 +17,6 @@ export const taskCardColors: TaskCardColors = { @@ -17,4 +17,6 @@ export const taskCardColors: TaskCardColors = {
$doneText: '#27771B',
$deleteBtn: '#E4B9B9',
$deleteText: '#870D0D',
$unAccessibleBtn: '#D3D3D3',
$unAccessibleTxt: '#BDBCBC',
}

Loading…
Cancel
Save