Skip to content

Commit

Permalink
feature(fe): unassign query example from dataset. Wrap action buttons…
Browse files Browse the repository at this point in the history
… into permissions provider
  • Loading branch information
AndreyNenashev committed Nov 27, 2023
1 parent bda7dec commit 2eed38c
Show file tree
Hide file tree
Showing 12 changed files with 271 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,16 @@ const DataEntityDetailsRoutes: React.FC = () => {
<RestrictedRoute
isAllowedTo={!isStatusDeleted}
redirectTo={`${DataEntityRoutes.overview}`}
component={DataEntityDetailsQueryExamples}
/>
>
<WithPermissionsProvider
allowedPermissions={[
Permission.QUERY_EXAMPLE_DATASET_CREATE,
Permission.QUERY_EXAMPLE_DATASET_DELETE,
]}
resourcePermissions={[]}
Component={DataEntityDetailsQueryExamples}
/>
</RestrictedRoute>
}
/>
</Routes>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,13 @@ import {
import { LinkIcon } from 'components/shared/icons';
import { useTranslation } from 'react-i18next';
import { useAppParams } from 'lib/hooks';
import { useGetQueryExamplesByDatasetId } from 'lib/hooks/api/dataModelling/queryExamples';
import {
useGetQueryExamplesByDatasetId,
useUnassignEntityQueryExample,
} from 'lib/hooks/api/dataModelling/queryExamples';
import AssignEntityQueryExampleForm from './AssignEntityQueryExampleForm';
import { WithPermissions } from '../../shared/contexts';
import { Permission } from '../../../generated-sources';

const DataEntityDetailsQueryExamples: React.FC = () => {
const { t } = useTranslation();
Expand All @@ -28,21 +33,27 @@ const DataEntityDetailsQueryExamples: React.FC = () => {
return (
<Grid container gap={2} mt={2}>
<Grid item display='flex' justifyContent='end' alignItems='center' xs={12}>
<AssignEntityQueryExampleForm
dataEntityId={dataEntityId}
openBtnEl={
<Button
buttonType='secondary-lg'
startIcon={<LinkIcon />}
text={t('Link query')}
/>
}
/>
<WithPermissions permissionTo={Permission.QUERY_EXAMPLE_DATASET_CREATE}>
<AssignEntityQueryExampleForm
dataEntityId={dataEntityId}
openBtnEl={
<Button
buttonType='secondary-lg'
startIcon={<LinkIcon />}
text={t('Link query')}
/>
}
/>
</WithPermissions>
</Grid>
<Grid item xs={12}>
<QueryExamplesListHeader />
{queryExamples.map(qe => (
<QueryExamplesListItem queryExample={qe} key={qe.definition} />
<QueryExamplesListItem
queryExample={qe}
key={qe.definition}
dataEntityId={dataEntityId}
/>
))}
{isLoading && <QueryExamplesSkeleton />}
{isEmpty && <EmptyContentPlaceholder />}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import React, { lazy } from 'react';
import { AppSuspenseWrapper } from 'components/shared/elements';
import { Navigate, Route, Routes } from 'react-router-dom';
import { DataModellingRoutes as routes } from 'routes/dataModellingRoutes';
import { Permission } from 'generated-sources';
import { WithPermissionsProvider } from '../shared/contexts';

const QueryExamplesContainer = lazy(() => import('./QueryExamplesContainer'));
const QueryExampleDetails = lazy(
Expand All @@ -12,10 +14,29 @@ const DataModellingRoutes: React.FC = () => (
<AppSuspenseWrapper>
<Routes>
<Route path='/' element={<Navigate to={routes.QUERY_EXAMPLES_PATH} />} />
<Route path={routes.QUERY_EXAMPLES_PATH} element={<QueryExamplesContainer />} />
<Route path={routes.QUERY_EXAMPLES_PATH}>
<Route path={routes.QUERY_EXAMPLE_PATH} element={<QueryExampleDetails />} />
</Route>
<Route
path={routes.QUERY_EXAMPLES_PATH}
element={
<WithPermissionsProvider
allowedPermissions={[Permission.QUERY_EXAMPLE_CREATE]}
resourcePermissions={[]}
render={() => <QueryExamplesContainer />}
/>
}
/>
<Route
path={routes.QUERY_EXAMPLE_PATH}
element={
<WithPermissionsProvider
allowedPermissions={[
Permission.QUERY_EXAMPLE_UPDATE,
Permission.QUERY_EXAMPLE_DELETE,
]}
resourcePermissions={[]}
render={() => <QueryExampleDetails />}
/>
}
/>
</Routes>
</AppSuspenseWrapper>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { Grid } from '@mui/material';
import { useTranslation } from 'react-i18next';
import { AddIcon } from 'components/shared/icons';
import useCreateQueryExampleSearch from 'lib/hooks/useCreateQueryExampleSearch';
import { WithPermissions } from 'components/shared/contexts';
import { Permission } from 'generated-sources';
import QueryExampleSearchInput from './QueryExampleSearchInput/QueryExampleSearchInput';
import QueryExampleSearchResults from './QueryExampleSearchResults/QueryExampleSearchResults';
import DataModellingTabs from './DataModellingTabs';
Expand All @@ -24,16 +26,17 @@ const QueryExamplesContainer: React.FC = () => {
xs={12}
>
<QueryExampleSearchInput facets={facets} />

<QueryExampleForm
btnCreateEl={
<Button
buttonType='main-lg'
startIcon={<AddIcon />}
text={t('Add query example')}
/>
}
/>
<WithPermissions permissionTo={Permission.QUERY_EXAMPLE_CREATE}>
<QueryExampleForm
btnCreateEl={
<Button
buttonType='main-lg'
startIcon={<AddIcon />}
text={t('Add query example')}
/>
}
/>
</WithPermissions>
</Grid>
<Grid item xs={12}>
<DataModellingTabs />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,13 @@ const QueryExamplesListHeader = () => {
<Grid item xs={4} pl={theme => theme.spacing(1)}>
<Typography variant='caption'>{t('Definition')}</Typography>
</Grid>
<Grid item xs={5} pl={theme => theme.spacing(1)}>
<Grid item xs={4} pl={theme => theme.spacing(1)}>
<Typography variant='caption'>{t('Query')}</Typography>
</Grid>
<Grid item xs={3} pl={theme => theme.spacing(1)}>
<Typography variant='caption'>{t('Linked entities')}</Typography>
</Grid>
<Grid item xs={1} pl={theme => theme.spacing(1)} />
</Grid>
);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,51 +1,64 @@
import { Grid } from '@mui/material';
import { Box, Grid } from '@mui/material';
import React from 'react';
import type { QueryExample } from 'generated-sources';
import { Permission } from 'generated-sources';
import { useAppPaths, useScrollBarWidth } from 'lib/hooks';
import { useNavigate } from 'react-router-dom';
import Button from 'components/shared/elements/Button/Button';
import { PreviewIcon, UnlinkIcon } from 'components/shared/icons';
import styled, { css } from 'styled-components';
import { WithPermissions } from 'components/shared/contexts';
import ConfirmationDialog from 'components/shared/elements/ConfirmationDialog/ConfirmationDialog';
import { useTranslation } from 'react-i18next';
import { useUnassignEntityQueryExample } from 'lib/hooks/api/dataModelling/queryExamples';
import TruncatedCell from '../TruncatedCell/TruncatedCell';
import Markdown from '../Markdown/Markdown';
import CollapsibleInfoContainer from '../CollapsibleInfoContainer/CollapsibleInfoContainer';

const StyledGridContainer = styled(Grid)<{ $scrollbarWidth: string }>(
({ theme, $scrollbarWidth }) => css`
padding-right: ${$scrollbarWidth};
border-bottom: 1px solid ${theme.palette.divider};
interface QueryExampleSearchResultsItemProps {
queryExample: QueryExample;
dataEntityId?: number;
}

const HiddenBox = styled(Box)(
({ theme }) => css`
display: none;
gap: ${theme.spacing(1)};
`
);

const ListItemContainer = styled(Grid)(
({ theme }) => css`
flex-wrap: nowrap;
align-items: center;
justify-content: center;
border-bottom: 1px solid ${theme.palette.divider};
&:hover {
background-color: ${theme.palette.backgrounds.primary};
cursor: pointer;
${HiddenBox} {
display: flex;
}
}
`
);

interface QueryExampleSearchResultsItemProps {
queryExample: QueryExample;
}

const QueryExamplesListItem = ({ queryExample }: QueryExampleSearchResultsItemProps) => {
const QueryExamplesListItem = ({
queryExample,
dataEntityId,
}: QueryExampleSearchResultsItemProps) => {
const scrollbarWidth = useScrollBarWidth();
const navigate = useNavigate();
const { queryExamplePath } = useAppPaths();
const { t } = useTranslation();
const { mutateAsync } = useUnassignEntityQueryExample();

return (
<StyledGridContainer
onClick={() => navigate(queryExamplePath(queryExample.id))}
key={queryExample.id}
container
$scrollbarWidth={scrollbarWidth}
>
<ListItemContainer key={queryExample.id} container pr={scrollbarWidth}>
<Grid item xs={4} p={1}>
<CollapsibleInfoContainer
style={{ border: 'none' }}
initialMaxHeight={96}
content={<Markdown value={queryExample.definition} disableCopy />}
/>
</Grid>
<Grid item xs={5} p={1}>
<Grid item xs={4} p={1}>
<CollapsibleInfoContainer
style={{ border: 'none' }}
initialMaxHeight={96}
Expand All @@ -55,7 +68,34 @@ const QueryExamplesListItem = ({ queryExample }: QueryExampleSearchResultsItemPr
<Grid item xs={3} p={1} alignItems='center'>
<TruncatedCell dataList={queryExample.linkedEntities} externalEntityId={1} />
</Grid>
</StyledGridContainer>
<Grid item xs={1} p={1} alignItems='center'>
<HiddenBox>
<Button
buttonType='linkGray-m-icon'
icon={<PreviewIcon />}
to={queryExamplePath(queryExample.id)}
/>
<WithPermissions permissionTo={Permission.QUERY_EXAMPLE_DATASET_DELETE}>
<ConfirmationDialog
actionTitle={t('Are you sure you want to unlink this query example?')}
actionName={t('Unlink')}
actionText={
<>
Query example #{queryExample.id} {t('will be unlinked')}.
</>
}
onConfirm={() =>
mutateAsync({
exampleId: queryExample.id,
dataEntityId: dataEntityId ?? 0,
})
}
actionBtn={<Button buttonType='linkGray-m-icon' icon={<UnlinkIcon />} />}
/>
</WithPermissions>
</HiddenBox>
</Grid>
</ListItemContainer>
);
};

Expand Down
36 changes: 36 additions & 0 deletions odd-platform-ui/src/components/shared/icons/PreviewIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import React from 'react';
import { type SvgIconProps } from '@mui/material/SvgIcon';
import AppSvgIcon from 'components/shared/icons/AppSvgIcon';

const PreviewIcon: React.FC<SvgIconProps> = ({ sx, ...props }) => (
<AppSvgIcon sx={sx} viewBox='0 0 24 24' {...props}>
<svg
xmlns='http://www.w3.org/2000/svg'
width='16'
height='16'
viewBox='0 0 16 16'
fill='none'
>
<path
fillRule='evenodd'
clipRule='evenodd'
d='M2.07868 8.31131C1.97402 8.11731 1.97402 7.88198 2.07868 7.68798C3.34002 5.35531 5.67002 3.33331 8.00002 3.33331C10.33 3.33331 12.66 5.35531 13.9213 7.68865C14.026 7.88265 14.026 8.11798 13.9213 8.31198C12.66 10.6446 10.33 12.6666 8.00002 12.6666C5.67002 12.6666 3.34002 10.6446 2.07868 8.31131Z'
stroke='#091E42'
strokeWidth='2'
strokeLinecap='round'
strokeLinejoin='round'
/>
<path
fillRule='evenodd'
clipRule='evenodd'
d='M9.41422 6.58577C10.1953 7.36681 10.1953 8.63315 9.41422 9.41419C8.63317 10.1952 7.36684 10.1952 6.58579 9.41419C5.80474 8.63315 5.80474 7.36681 6.58579 6.58577C7.36684 5.80472 8.63317 5.80472 9.41422 6.58577Z'
stroke='#091E42'
strokeWidth='2'
strokeLinecap='round'
strokeLinejoin='round'
/>
</svg>
</AppSvgIcon>
);

export default PreviewIcon;
Loading

0 comments on commit 2eed38c

Please sign in to comment.