diff --git a/src/pages/stories/Stories.tsx b/src/pages/stories/Stories.tsx index a31cb704ea..db96feadb9 100644 --- a/src/pages/stories/Stories.tsx +++ b/src/pages/stories/Stories.tsx @@ -1,13 +1,12 @@ -import '@tremor/react/dist/esm/tremor.css'; - -import { Button as BpButton, Icon as BpIcon, NonIdealState } from '@blueprintjs/core'; +import { Button, InputGroup, NonIdealState } from '@blueprintjs/core'; import { IconNames } from '@blueprintjs/icons'; -import { Card, Flex, TextInput, Title } from '@tremor/react'; import React, { useCallback, useState } from 'react'; import { useDispatch } from 'react-redux'; import { useNavigate } from 'react-router-dom'; import { StoriesRole } from 'src/commons/application/ApplicationTypes'; import ContentDisplay from 'src/commons/ContentDisplay'; +import GradingFlex from 'src/commons/grading/GradingFlex'; +import GradingText from 'src/commons/grading/GradingText'; import { showSimpleConfirmDialog } from 'src/commons/utils/DialogHelper'; import { useTypedSelector } from 'src/commons/utils/Hooks'; import StoriesActions from 'src/features/stories/StoriesActions'; @@ -120,23 +119,25 @@ const Stories: React.FC = () => { dispatch(StoriesActions.getStoriesList())} display={ - - - - All Stories + <> + + + All Stories {isLoggedIn && ( - + )} - - } + + setQuery(e.target.value)} /> - + { ); }} /> - + } /> ); diff --git a/src/pages/stories/StoriesTable.tsx b/src/pages/stories/StoriesTable.tsx index f0f88391eb..d66d73379a 100644 --- a/src/pages/stories/StoriesTable.tsx +++ b/src/pages/stories/StoriesTable.tsx @@ -1,18 +1,14 @@ -import { Icon as BpIcon } from '@blueprintjs/core/lib/esm/components/icon/icon'; +import 'ag-grid-community/styles/ag-grid.css'; +import 'ag-grid-community/styles/ag-theme-quartz.css'; + +import { Icon } from '@blueprintjs/core'; import { IconNames } from '@blueprintjs/icons'; -import { - Flex, - Icon, - Table, - TableBody, - TableCell, - TableHead, - TableHeaderCell, - TableRow, - Text -} from '@tremor/react'; -import React from 'react'; +import { ColDef } from 'ag-grid-community'; +import { AgGridReact, CustomCellRendererProps } from 'ag-grid-react'; +import React, { useMemo } from 'react'; +import GradingFlex from 'src/commons/grading/GradingFlex'; import { StoryListView } from 'src/features/stories/StoriesTypes'; +import classes from 'src/styles/Stories.module.scss'; type Props = { headers: Array<{ id: string; header: string }>; @@ -22,45 +18,63 @@ type Props = { const MAX_EXCERPT_LENGTH = 35; +const truncate = (content: string) => { + return content.replaceAll(/\s+/g, ' ').length <= MAX_EXCERPT_LENGTH + ? content.replaceAll(/\s+/g, ' ') + : content.split(/\s+/).reduce((acc, cur) => { + return acc.length + cur.length <= MAX_EXCERPT_LENGTH ? acc + ' ' + cur : acc; + }, '') + '…'; +}; + +const defaultColDef: ColDef = { + cellClass: ({ data }) => (data?.isPinned ? classes['highlight-row'] : '') +}; + const StoriesTable: React.FC = ({ headers, stories, storyActions }) => { + const columns: ColDef[] = useMemo( + () => [ + { flex: 2, field: 'authorName', headerName: 'Author' }, + { + flex: 4, + field: 'title', + headerName: 'Title', + cellRenderer: ({ data, value }: CustomCellRendererProps) => + data && ( + + {data.isPinned && } + {value} + + ) + }, + { + flex: 6, + field: 'content', + headerName: 'Content', + valueFormatter: ({ value }) => truncate(value), + cellStyle: { textAlign: 'left' } + }, + { + flex: 3, + field: 'actions' as any, + headerName: 'Actions', + sortable: false, + cellRenderer: ({ data }: CustomCellRendererProps) => storyActions(data!) + } + ], + [storyActions] + ); + return ( - - - - {headers.map(({ id, header }) => ( - {header} - ))} - - - - {stories.map(story => { - const { id, authorName, isPinned, title, content } = story; - return ( - - {authorName} - - - {isPinned && } />} - {title} - - - - - {content.replaceAll(/\s+/g, ' ').length <= MAX_EXCERPT_LENGTH - ? content.replaceAll(/\s+/g, ' ') - : content.split(/\s+/).reduce((acc, cur) => { - return acc.length + cur.length <= MAX_EXCERPT_LENGTH - ? acc + ' ' + cur - : acc; - }, '') + '…'} - - - {storyActions(story)} - - ); - })} - -
+
+ +
); }; diff --git a/src/pages/stories/Story.tsx b/src/pages/stories/Story.tsx index c629a226ac..676eb59cc1 100644 --- a/src/pages/stories/Story.tsx +++ b/src/pages/stories/Story.tsx @@ -1,7 +1,6 @@ import 'js-slang/dist/editors/ace/theme/source'; -import { Classes } from '@blueprintjs/core'; -import { TextInput } from '@tremor/react'; +import { Classes, InputGroup } from '@blueprintjs/core'; import classNames from 'classnames'; import { useEffect, useState } from 'react'; import AceEditor, { IEditorProps } from 'react-ace'; @@ -57,8 +56,8 @@ const Story: React.FC = ({ isViewOnly = false }) => { isViewOnly ? ( <>{title} ) : ( - { diff --git a/src/pages/stories/StoryActions.tsx b/src/pages/stories/StoryActions.tsx index db5f1e020c..cedbef6218 100644 --- a/src/pages/stories/StoryActions.tsx +++ b/src/pages/stories/StoryActions.tsx @@ -1,8 +1,8 @@ -import { Icon as BpIcon } from '@blueprintjs/core'; +import { Button, Position, Tooltip } from '@blueprintjs/core'; import { IconNames } from '@blueprintjs/icons'; -import { Flex, Icon } from '@tremor/react'; import React from 'react'; -import { Link } from 'react-router-dom'; +import { useNavigate } from 'react-router-dom'; +import GradingFlex from 'src/commons/grading/GradingFlex'; type Props = { storyId: number; @@ -29,69 +29,88 @@ const StoryActions: React.FC = ({ handleMovePinUp = () => {}, handleMovePinDown = () => {} }) => { + const navigate = useNavigate(); return ( - + {canView && ( - - } - variant="light" - color="green" + + - + )} {canPin && ( - + )} {canDelete && ( - + )} - + ); }; diff --git a/src/styles/Stories.module.scss b/src/styles/Stories.module.scss new file mode 100644 index 0000000000..f2bbf3a3c0 --- /dev/null +++ b/src/styles/Stories.module.scss @@ -0,0 +1,5 @@ +@import '_global'; + +.highlight-row { + background-color: #e0f2fe; +}