Skip to content

Commit

Permalink
feat: adding frontend and backend feature flags (#817)
Browse files Browse the repository at this point in the history
### Feature or Bugfix
- Feature

### Detail
- Adding frontend support for all feature flags defined in config.json
with a new util method isFeatureEnabled
- Adding a new flag **preview_data** in the datasets module to control
whether previewing data is allowed
- Adding a new flag **glue_crawler** in the datasets module to control
whether running glue crawler is allowed
- Updating environment features to be hidden or visible based on whether
the module is active. Adding a new util isAnyFeatureModuleEnabled to
check whether to render the entire feature box.

### Relates
N/A

### Security
Not relevant

By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache 2.0 license.

---------

Co-authored-by: Zilvinas Saltys <zilvinas.saltys@yahooinc.com>
  • Loading branch information
zsaltys and zsaltys authored Oct 25, 2023
1 parent 8b7b82e commit 48c32e5
Show file tree
Hide file tree
Showing 14 changed files with 444 additions and 341 deletions.
1 change: 1 addition & 0 deletions backend/dataall/modules/datasets/api/dataset/resolvers.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ def get_dataset_assume_role_url(context: Context, source, datasetUri: str = None
return DatasetService.get_dataset_assume_role_url(uri=datasetUri)


@is_feature_enabled('modules.datasets.features.glue_crawler')
def start_crawler(context: Context, source, datasetUri: str, input: dict = None):
return DatasetService.start_crawler(uri=datasetUri, data=input)

Expand Down
2 changes: 2 additions & 0 deletions backend/dataall/modules/datasets/api/table/resolvers.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import logging

from dataall.core.feature_toggle_checker import is_feature_enabled
from dataall.modules.catalog.db.glossary_repositories import GlossaryRepository
from dataall.modules.datasets.api.dataset.resolvers import get_dataset
from dataall.base.api.context import Context
Expand All @@ -23,6 +24,7 @@ def delete_table(context, source, tableUri: str = None):
return DatasetTableService.delete_table(uri=tableUri)


@is_feature_enabled('modules.datasets.features.preview_data')
def preview(context, source, tableUri: str = None):
if not tableUri:
return None
Expand Down
4 changes: 3 additions & 1 deletion config.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@
"features": {
"file_uploads": true,
"file_actions": true,
"aws_actions": true
"aws_actions": true,
"preview_data": true,
"glue_crawler": true
}
},
"worksheets": {
Expand Down
9 changes: 6 additions & 3 deletions frontend/src/modules/Datasets/components/DatasetData.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import React from 'react';
import { Box } from '@mui/material';
import { DatasetTables } from './DatasetTables';
import { DatasetFolders } from './DatasetFolders';
import { isFeatureEnabled } from 'utils';

export const DatasetData = (props) => {
const { dataset, isAdmin } = props;
Expand All @@ -12,9 +13,11 @@ export const DatasetData = (props) => {
<Box>
<DatasetTables dataset={dataset} isAdmin={isAdmin} />
</Box>
<Box sx={{ mt: 3 }}>
<DatasetFolders dataset={dataset} isAdmin={isAdmin} />
</Box>
{isFeatureEnabled('datasets', 'file_actions') && (
<Box sx={{ mt: 3 }}>
<DatasetFolders dataset={dataset} isAdmin={isAdmin} />
</Box>
)}
</Box>
);
};
Expand Down
21 changes: 12 additions & 9 deletions frontend/src/modules/Datasets/components/DatasetTables.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import { listDatasetTables, deleteDatasetTable, useClient } from 'services';
import { syncTables } from '../services';

import { DatasetStartCrawlerModal } from './DatasetStartCrawlerModal';
import { isFeatureEnabled } from 'utils';

export const DatasetTables = (props) => {
const { dataset, isAdmin } = props;
Expand Down Expand Up @@ -216,15 +217,17 @@ export const DatasetTables = (props) => {
Synchronize
</LoadingButton>

<LoadingButton
color="primary"
onClick={handleStartCrawlerModalOpen}
startIcon={<SearchIcon fontSize="small" />}
sx={{ m: 1 }}
variant="outlined"
>
Start Crawler
</LoadingButton>
{isFeatureEnabled('datasets', 'glue_crawler') && (
<LoadingButton
color="primary"
onClick={handleStartCrawlerModalOpen}
startIcon={<SearchIcon fontSize="small" />}
sx={{ m: 1 }}
variant="outlined"
>
Start Crawler
</LoadingButton>
)}
</Grid>
)}
</Box>
Expand Down
17 changes: 11 additions & 6 deletions frontend/src/modules/Datasets/views/DatasetView.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import {
DatasetOverview,
DatasetUpload
} from '../components';
import { isFeatureEnabled } from 'utils';

const DatasetView = () => {
const dispatch = useDispatch();
Expand Down Expand Up @@ -81,11 +82,13 @@ const DatasetView = () => {
value: 'shares',
icon: <ShareOutlined fontSize="small" />
});
tabs.push({
label: 'Upload',
value: 'upload',
icon: <Upload fontSize="small" />
});
if (isFeatureEnabled('datasets', 'file_uploads')) {
tabs.push({
label: 'Upload',
value: 'upload',
icon: <Upload fontSize="small" />
});
}
if (settings.isAdvancedMode) {
tabs.push({
label: 'Tags',
Expand Down Expand Up @@ -278,7 +281,9 @@ const DatasetView = () => {
>
Chat
</Button>
<DatasetAWSActions dataset={dataset} isAdmin={isAdmin} />
{isFeatureEnabled('datasets', 'aws_actions') && (
<DatasetAWSActions dataset={dataset} isAdmin={isAdmin} />
)}
<Button
color="primary"
component={RouterLink}
Expand Down
82 changes: 43 additions & 39 deletions frontend/src/modules/Environments/components/EnvironmentFeatures.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,46 +41,50 @@ export const EnvironmentFeatures = (props) => {
// Filter the features based on the 'active' attribute
const activeFeatures = features.filter((feature) => feature.active);

return (
<Card {...other}>
<CardHeader title="Features" />
<Divider />
<CardContent sx={{ pt: 0 }}>
<List>
{activeFeatures.map((feature) => (
<ListItem
key={feature.title}
disableGutters
divider
sx={{
justifyContent: 'space-between',
padding: 2
}}
>
<Typography color="textSecondary" variant="subtitle2">
{feature.title}
</Typography>
<Typography color="textPrimary" variant="body2">
<Label
color={
environment.parameters[feature.enabledEnvVariableName] ===
if (activeFeatures.length === 0) {
return <></>;
} else {
return (
<Card {...other}>
<CardHeader title="Features" />
<Divider />
<CardContent sx={{ pt: 0 }}>
<List>
{activeFeatures.map((feature) => (
<ListItem
key={feature.title}
disableGutters
divider
sx={{
justifyContent: 'space-between',
padding: 2
}}
>
<Typography color="textSecondary" variant="subtitle2">
{feature.title}
</Typography>
<Typography color="textPrimary" variant="body2">
<Label
color={
environment.parameters[feature.enabledEnvVariableName] ===
'true'
? 'success'
: 'error'
}
>
{environment.parameters[feature.enabledEnvVariableName] ===
'true'
? 'success'
: 'error'
}
>
{environment.parameters[feature.enabledEnvVariableName] ===
'true'
? 'Enabled'
: 'Disabled'}
</Label>
</Typography>
</ListItem>
))}
</List>
</CardContent>
</Card>
);
? 'Enabled'
: 'Disabled'}
</Label>
</Typography>
</ListItem>
))}
</List>
</CardContent>
</Card>
);
}
};

EnvironmentFeatures.propTypes = {
Expand Down
58 changes: 32 additions & 26 deletions frontend/src/modules/Environments/components/EnvironmentTeams.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ import {
import { EnvironmentRoleAddForm } from './EnvironmentRoleAddForm';
import { EnvironmentTeamInviteEditForm } from './EnvironmentTeamInviteEditForm';
import { EnvironmentTeamInviteForm } from './EnvironmentTeamInviteForm';
import { isFeatureEnabled } from '../../../utils';

function TeamRow({ team, environment, fetchItems }) {
const client = useClient();
Expand Down Expand Up @@ -176,34 +177,39 @@ function TeamRow({ team, environment, fetchItems }) {
/>
)}
</TableCell>

<TableCell>
<Box>
<LoadingButton
loading={accessingConsole}
onClick={() => getConsoleLink(team.groupUri)}
>
<FaIcons.FaAws
size={25}
color={
theme.palette.mode === 'dark'
? theme.palette.primary.contrastText
: theme.palette.primary.main
}
/>
</LoadingButton>
<LoadingButton
loading={loadingCreds}
onClick={() => generateCredentials(team.groupUri)}
>
<CopyAllOutlined
sx={{
color:
theme.palette.mode === 'dark'
? theme.palette.primary.contrastText
: theme.palette.primary.main
}}
/>
</LoadingButton>
{isFeatureEnabled('core', 'env_aws_actions') && (
<>
<LoadingButton
loading={accessingConsole}
onClick={() => getConsoleLink(team.groupUri)}
>
<FaIcons.FaAws
size={25}
color={
theme.palette.mode === 'dark'
? theme.palette.primary.contrastText
: theme.palette.primary.main
}
/>
</LoadingButton>
<LoadingButton
loading={loadingCreds}
onClick={() => generateCredentials(team.groupUri)}
>
<CopyAllOutlined
sx={{
color:
theme.palette.mode === 'dark'
? theme.palette.primary.contrastText
: theme.palette.primary.main
}}
/>
</LoadingButton>
</>
)}
{team.groupUri !== environment.SamlGroupName && (
<LoadingButton onClick={() => removeGroup(team.groupUri)}>
<HiUserRemove
Expand Down
Loading

0 comments on commit 48c32e5

Please sign in to comment.