entity-author.js 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. import { useCurrentUser } from 'app/context/user';
  2. import { View, Row } from 'app/design/view';
  3. import Time from 'app/ui/atoms/time';
  4. import Profile from 'app/ui/molecules/profile/profile';
  5. import DropdownMenu from 'app/ui/atoms/dropdown-menu';
  6. import Link from 'app/ui/atoms/link'
  7. import { Text } from 'app/design/typography'
  8. import { fetcher } from 'app/lib/fetcher'
  9. import Redirect from 'app/ui/atoms/redirect'
  10. import { useRef, useState } from 'react';
  11. import useFetchForm from 'app/lib/hooks/use-fetch-form'
  12. import { Modal } from 'app/design/controls'
  13. import Form from 'app/components/elements/form'
  14. import FormModal, { handleFormModal } from 'app/ui/molecules/dialogs/form-modal';
  15. import { useIsDesktop } from 'app/context/measure';
  16. import { BlockWrapper } from 'app/components/block-wrapper'
  17. import { runMenuItemCallback } from 'app/lib/util'
  18. import { useTranslation } from 'react-i18next'
  19. export default function ElementEntityAuthor({ data, blockWrapperProps }) {
  20. const { t } = useTranslation();
  21. const { currentUser } = useCurrentUser();
  22. const [viewState, setViewState] = useState({ view: '' })
  23. const [postData, setPostData] = useState(null)
  24. const [pageData, setPageData] = useState(false);
  25. const isDesktop = useIsDesktop();
  26. const context = data?.entry_context;
  27. const contextUrl = typeof context?.url === 'string' ? context.url.trim() : '';
  28. const isContextLinkable = contextUrl && !/^\/?javascript:/i.test(contextUrl);
  29. const contextIdentity = context ? (
  30. <Row className='items-center gap-x-1 justify-start'>
  31. <Profile {...context} displayType="unit_wo_info" displaySize="2xs" showLinks={false} />
  32. <Text className="text-secondary-foreground text-xs leading-5 text-center font-medium ">{context.display_name}</Text>
  33. </Row>
  34. ) : null;
  35. const sInfo = (
  36. <Row className='flex-none gap-1 items-center justify-start text-muted-foreground text-sm font-medium leading-5 '>
  37. <Time className="text-muted-foreground text-xs leading-5 text-center font-medium " size="xs"
  38. ts={data.entry_date}
  39. />
  40. {
  41. !!context?.id && (
  42. <Row className='items-center gap-x-1 justify-start'>
  43. <Text className=" text-center font-medium leading-5 text-xs text-secondary-foreground">{t('in')}</Text>
  44. {isContextLinkable ? (
  45. <Link href={contextUrl} size="xs" variant="secondary">
  46. {contextIdentity}
  47. </Link>
  48. ) : contextIdentity}
  49. </Row>
  50. )}
  51. </Row>
  52. );
  53. let handleMenuManageSelect = false
  54. const item_id = data?.entry_id;
  55. const redirectdRef = useRef();
  56. // Submit edit form; UI refresh comes via bx_timeline_0 "edited" socket
  57. useFetchForm('/api.php?r=bx_timeline/get_edit_form/&params[]=' + item_id, postData);
  58. const onFormSubmit = (formData, d) => {
  59. setViewState({ view: '' })
  60. setPostData(formData);
  61. }
  62. let aMenuManageItems = [];
  63. if (!!currentUser && data?.menu_manage?.items) {
  64. data.menu_manage.items.forEach((aItem) => {
  65. if (aItem?.display_type && (aItem.display_type != 'link' && aItem.display_type != 'callback' && aItem.name != 'report'))
  66. return;
  67. aMenuManageItems.push({
  68. id: aItem.id ? aItem.id : aItem.name,
  69. link: '/' + aItem.link,
  70. name: aItem.name,
  71. title: aItem?.title ? aItem?.title : '',
  72. icon: aItem.icon,
  73. image: aItem.image,
  74. data: aItem.data,
  75. });
  76. });
  77. }
  78. aMenuManageItems = aMenuManageItems.filter((item) => (item.title != ''))
  79. if (data?.menu_manage?.object == 'bx_timeline_menu_item_manage') {
  80. handleMenuManageSelect = async (oItem, event) => {
  81. switch (oItem.name) {
  82. case 'item-edit':
  83. setPageData('loading');
  84. const oResultEdit = await fetcher(
  85. '/api.php?r=bx_timeline/get_edit_form/&params[]=' + item_id
  86. )
  87. setViewState({ view: 'edited', data: oResultEdit.data.form })
  88. break
  89. case 'item-delete':
  90. setPageData('loading');
  91. const oResultDeleted = await fetcher(
  92. '/api.php?r=bx_timeline/delete/&params[]=' + item_id
  93. )
  94. redirectdRef.current.redirect('/');
  95. break
  96. default:
  97. await runMenuItemCallback(oItem)
  98. break
  99. }
  100. }
  101. }
  102. else {
  103. handleMenuManageSelect = handleFormModal;
  104. }
  105. const menuOptions = handleMenuManageSelect ? { onSelect: (oItem, event) => handleMenuManageSelect(oItem, event, setPageData) } : {};
  106. return (
  107. <BlockWrapper {...blockWrapperProps}>
  108. <Row className="justify-between gap-2">
  109. <FormModal pageData={pageData} setPageData={setPageData} />
  110. <Redirect ref={redirectdRef} />
  111. {viewState.view == 'edited' && (<Modal
  112. onVisible={true}
  113. transparent={true}
  114. headerBorder={true}
  115. padding=' '
  116. >
  117. <Form
  118. {...viewState.data}
  119. classContainerName="flex-row flex-wrap px-2 w-full items-start justify-between"
  120. onFormSubmit={onFormSubmit}
  121. exProps={{
  122. onClose: () => { setViewState({ view: '' }) }
  123. }}
  124. />
  125. </Modal>)
  126. }
  127. <View className={data.text ? '' : 'flex-auto'}>
  128. <Profile {...data.author_data} displayType="unit" displaySize="base" className='hidden lg:flex' showInfo={sInfo} />
  129. </View>
  130. {(data.text && false) && (
  131. <View className='flex-auto overflow-hidden text-ellipsis w-1/2 lg:w-auto px-4'>
  132. <Link href={data.url}>
  133. <Text className=" lg:text-center overflow-hidden text-ellipsis text-lg font-bold text-popover-foreground overflow" numberOfLines={2}>
  134. {data.text}
  135. </Text>
  136. </Link>
  137. </View>
  138. )
  139. }
  140. <View>
  141. {aMenuManageItems.length > 0 &&
  142. <DropdownMenu
  143. mode="popup"
  144. items={aMenuManageItems}
  145. {...menuOptions}
  146. buttonProps={{
  147. image: 'Ellipsis',
  148. style: 'borderless',
  149. borderShape: 'circle',
  150. controlSize: 'regular',
  151. accessibilityLabel: 'More options',
  152. }}
  153. />
  154. }
  155. </View>
  156. </Row>
  157. </BlockWrapper>
  158. );
  159. }