Skip to content

Commit

Permalink
Update database and add feature flag page under entities
Browse files Browse the repository at this point in the history
  • Loading branch information
gebbing12 committed Nov 11, 2024
1 parent 7dd08a3 commit 99c6d5a
Show file tree
Hide file tree
Showing 14 changed files with 360 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ public class FeatureFlag implements Serializable {
@Column(name = "description")
private String description;

@Column(name = "enabled")
private Boolean enabled;
@Column(name = "enabled", nullable = false, columnDefinition = "boolean default false")
private Boolean enabled = false;

@ManyToMany
@JoinTable(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,19 @@
<!--
Added the entity FeatureFlag.
-->
<changeSet id="20241024231608-1" author="jhipster">
<changeSet id="20241024231608-1" author="oncokb">
<createTable tableName="feature_flag">
<column name="id" type="bigint" autoIncrement="true">
<constraints primaryKey="true" nullable="false"/>
</column>
<column name="name" type="varchar(50)">
<column name="name" type="varchar(255)">
<constraints nullable="false" />
</column>
<column name="description" type="varchar(200)">
<column name="description" type="varchar(255)">
<constraints nullable="true" />
</column>
<column name="enabled" type="boolean">
<constraints nullable="true" />
<constraints nullable="false" default="false"/>
</column>
<!-- jhipster-needle-liquibase-add-column - JHipster will add columns here -->
</createTable>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<!--
Added the constraints for entity FeatureFlag.
-->
<changeSet id="20241024231608-2" author="jhipster">
<changeSet id="20241024231608-2" author="oncokb">

<addForeignKeyConstraint baseColumnNames="feature_flag_id"
baseTableName="rel_feature_flag__user"
Expand Down
22 changes: 17 additions & 5 deletions src/main/webapp/app/components/sidebar/NavigationSidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ const ENTITY_MENU_NAME: { [key in ENTITY_TYPE]?: string } = {
[ENTITY_TYPE.ENSEMBL_GENE]: 'Ensembl Gene',
[ENTITY_TYPE.FDA_DRUG]: 'FDA Drug',
[ENTITY_TYPE.FDA_SUBMISSION]: 'FDA Submission',
[ENTITY_TYPE.FEATURE_FLAG]: 'Feature Flag',
[ENTITY_TYPE.FLAG]: 'Flag',
[ENTITY_TYPE.GENE]: 'Gene',
[ENTITY_TYPE.GENOMIC_INDICATOR]: 'Genomic Indicator',
Expand All @@ -70,6 +71,7 @@ const DEFAULT_ENTITY_MENU_ORDER: ENTITY_TYPE[] = [
ENTITY_TYPE.ENSEMBL_GENE,
ENTITY_TYPE.FDA_DRUG,
ENTITY_TYPE.FDA_SUBMISSION,
ENTITY_TYPE.FEATURE_FLAG,
ENTITY_TYPE.FLAG,
ENTITY_TYPE.GENE,
ENTITY_TYPE.GENOMIC_INDICATOR,
Expand Down Expand Up @@ -257,11 +259,21 @@ export const NavigationSidebar: React.FunctionComponent<StoreProps> = ({ isNavSi
nav={<NavLink to={PAGE_ROUTE.SEARCH} />}
/>
<SubMenu defaultOpen label="Entities" icon={<GoDatabase size={DEFAULT_NAV_ICON_SIZE} />}>
{entityMenuOrder.map(entityType => (
<PriorityEntityMenuItem key={entityType} type={entityType} handlePriorityMenuItemClick={handlePriorityMenuItemClick}>
{ENTITY_MENU_NAME[entityType]}
</PriorityEntityMenuItem>
))}
{entityMenuOrder
.filter(entityType => {
return entityType !== ENTITY_TYPE.FEATURE_FLAG || props.isAdmin;
})
.map(entityType => {
return (
<PriorityEntityMenuItem
key={entityType}
type={entityType}
handlePriorityMenuItemClick={handlePriorityMenuItemClick}
>
{ENTITY_MENU_NAME[entityType]}
</PriorityEntityMenuItem>
);
})}
</SubMenu>
</>
)}
Expand Down
7 changes: 7 additions & 0 deletions src/main/webapp/app/config/constants/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ export enum ENTITY_TYPE {
FDA_SUBMISSION = 'fda-submission',
FDA_SUBMISSION_TYPE = 'fda-submission-type',
FLAG = 'flag',
FEATURE_FLAG = 'feature-flag',
GENE = 'gene',
GENOME_FRAGMENT = 'genome-fragment',
GENOMIC_INDICATOR = 'genomic-indicator',
Expand Down Expand Up @@ -87,6 +88,7 @@ export enum ENTITY_PAGE_ROUTE {
FDA_SUBMISSION = '/fda-submission',
FDA_SUBMISSION_TYPE = '/fda-submission-type',
FLAG = '/flag',
FEATURE_FLAG = '/feature-flag',
GENE = '/gene',
GENOME_FRAGMENT = '/genome-fragment',
GENOMIC_INDICATOR = '/genomic-indicator',
Expand Down Expand Up @@ -147,6 +149,7 @@ export enum ENTITY_RESOURCE_PATH {
FDA_SUBMISSION = '/fda-submissions',
FDA_SUBMISSION_TYPE = '/fda-submission-types',
FLAG = '/flags',
FEATURE_FLAG = '/feature-flags',
GENE = '/genes',
GENOME_FRAGMENT = '/genome-fragments',
GENOMIC_INDICATOR = '/genomic-indicators',
Expand Down Expand Up @@ -251,6 +254,10 @@ export const ENTITY_INFO: { [key in ENTITY_TYPE]: { pageRoute?: ENTITY_PAGE_ROUT
pageRoute: ENTITY_PAGE_ROUTE.FLAG,
resourcePath: ENTITY_RESOURCE_PATH.FLAG,
},
[ENTITY_TYPE.FEATURE_FLAG]: {
pageRoute: ENTITY_PAGE_ROUTE.FEATURE_FLAG,
resourcePath: ENTITY_RESOURCE_PATH.FEATURE_FLAG,
},
[ENTITY_TYPE.GENE]: {
pageRoute: ENTITY_PAGE_ROUTE.GENE,
resourcePath: ENTITY_RESOURCE_PATH.GENE,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import React, { useEffect } from 'react';
import { connect } from 'app/shared/util/typed-inject';
import { RouteComponentProps } from 'react-router-dom';
import { Modal, ModalHeader, ModalBody, ModalFooter, Button } from 'reactstrap';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { IRootStore } from 'app/stores';

export interface IFeatureFlagDeleteDialogProps extends StoreProps, RouteComponentProps<{ id: string }> {}

export const FeatureFlagDeleteDialog = (props: IFeatureFlagDeleteDialogProps) => {
useEffect(() => {
props.getEntity(props.match.params.id);
}, []);

const featureFlagEntity = props.featureFlagEntity;
const updateSuccess = props.updateSuccess;

const handleClose = () => {
props.history.push('/feature-flag' + props.location.search);
};

useEffect(() => {
if (updateSuccess) {
handleClose();
}
}, [updateSuccess]);

const confirmDelete = () => {
props.deleteEntity(featureFlagEntity.id);
};

return (
<Modal isOpen toggle={handleClose}>
<ModalHeader toggle={handleClose} data-cy="featureFlagDeleteDialogHeading">
Confirm delete operation
</ModalHeader>
<ModalBody id="oncokbCurationApp.featureFlag.delete.question">Are you sure you want to delete this FeatureFlag?</ModalBody>
<ModalFooter>
<Button color="secondary" onClick={handleClose}>
<FontAwesomeIcon icon="ban" />
&nbsp; Cancel
</Button>
<Button id="jhi-confirm-delete-featureFlag" data-cy="entityConfirmDeleteButton" color="danger" onClick={confirmDelete}>
<FontAwesomeIcon icon="trash" />
&nbsp; Delete
</Button>
</ModalFooter>
</Modal>
);
};

const mapStoreToProps = ({ featureFlagStore }: IRootStore) => ({
featureFlagEntity: featureFlagStore.entity,
updateSuccess: featureFlagStore.updateSuccess,
getEntity: featureFlagStore.getEntity,
deleteEntity: featureFlagStore.deleteEntity,
});

type StoreProps = ReturnType<typeof mapStoreToProps>;

export default connect(mapStoreToProps)(FeatureFlagDeleteDialog);
55 changes: 55 additions & 0 deletions src/main/webapp/app/entities/feature-flag/feature-flag-detail.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import React, { useEffect } from 'react';
import { connect } from 'app/shared/util/typed-inject';
import { Link, RouteComponentProps } from 'react-router-dom';
import { Button, Row, Col } from 'reactstrap';
import {} from 'react-jhipster';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { IRootStore } from 'app/stores';

export interface IFeatureFlagProps extends StoreProps, RouteComponentProps<{ id: string }> {}

export const FeatureFlagDetail = (props: IFeatureFlagProps) => {
useEffect(() => {
props.getEntity(props.match.params.id);
}, []);

const featureFlagEntity = props.featureFlagEntity;

return (
<Row>
<Col md="8">
<h2 data-cy="featureFlagDetailsHeading">FeatureFlag</h2>
<dl className="jh-entity-details">
<dt>
<span id="id">ID</span>
</dt>
<dd>{featureFlagEntity.id}</dd>
<dt>
<span id="code">Name</span>
</dt>
<dd>{featureFlagEntity.name}</dd>
<dt>
<span id="color">Description</span>
</dt>
<dd>{featureFlagEntity.description}</dd>
<dt>
<span id="level">Enabled</span>
</dt>
<dd>{featureFlagEntity.enabled ? 'true' : 'false'}</dd>
</dl>
<Button tag={Link} to={`/feature-flag/${featureFlagEntity.id}/edit`} replace color="primary">
<FontAwesomeIcon icon="pencil-alt" /> <span className="d-none d-md-inline">Edit</span>
</Button>
</Col>
</Row>
);
};

const mapStoreToProps = ({ featureFlagStore }: IRootStore) => ({
featureFlagEntity: featureFlagStore.entity,
getEntity: featureFlagStore.getEntity,
});

type StoreProps = ReturnType<typeof mapStoreToProps>;

export default connect(mapStoreToProps)(FeatureFlagDetail);
103 changes: 103 additions & 0 deletions src/main/webapp/app/entities/feature-flag/feature-flag-update.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import React, { useState, useEffect } from 'react';
import { connect } from 'app/shared/util/typed-inject';
import { RouteComponentProps } from 'react-router-dom';
import { Row, Col } from 'reactstrap';
import { ValidatedField, ValidatedForm } from 'react-jhipster';
import { IRootStore } from 'app/stores';
import { SaveButton } from 'app/shared/button/SaveButton';

export interface IFeatureFlagUpdateProps extends StoreProps, RouteComponentProps<{ id: string }> {}

export const FeatureFlagUpdate = (props: IFeatureFlagUpdateProps) => {
const [isNew] = useState(!props.match.params || !props.match.params.id);

const featureFlagEntity = props.featureFlagEntity;
const loading = props.loading;
const updating = props.updating;
const updateSuccess = props.updateSuccess;

const handleClose = () => {
props.history.push('/feature-flag' + props.location.search);
};

useEffect(() => {
if (isNew) {
props.reset();
} else {
props.getEntity(props.match.params.id);
}

props.getFeatureFlags({});
}, []);

useEffect(() => {
if (updateSuccess) {
handleClose();
}
}, [updateSuccess]);

const saveEntity = values => {
const entity = {
...featureFlagEntity,
...values,
};

if (isNew) {
props.createEntity(entity);
} else {
props.updateEntity(entity);
}
};

const defaultValues = () =>
isNew
? {}
: {
...featureFlagEntity,
enabled: featureFlagEntity.enabled ?? false,
};

return (
<div>
<Row className="justify-content-center">
<Col md="8">
<h2 id="oncokbCurationApp.featureFlag.home.createOrEditLabel" data-cy="FeatureFlagCreateUpdateHeading">
Add or edit a FeatureFlag
</h2>
</Col>
</Row>
<Row className="justify-content-center">
<Col md="8">
{loading ? (
<p>Loading...</p>
) : (
<ValidatedForm defaultValues={defaultValues()} onSubmit={saveEntity}>
{!isNew ? <ValidatedField name="id" required readOnly id="feature-flag-id" label="ID" validate={{ required: true }} /> : null}
<ValidatedField label="Name" id="feature-flag-name" name="name" data-cy="name" type="text" />
<ValidatedField label="Description" id="feature-flag-description" name="description" data-cy="description" type="textarea" />
<ValidatedField label="Enabled" id="feature-flag-enabled" name="enabled" data-cy="enabled" check type="checkbox" />
<SaveButton disabled={updating} />
</ValidatedForm>
)}
</Col>
</Row>
</div>
);
};

const mapStoreToProps = (storeState: IRootStore) => ({
featureFlags: storeState.featureFlagStore.entities,
featureFlagEntity: storeState.featureFlagStore.entity,
loading: storeState.featureFlagStore.loading,
updating: storeState.featureFlagStore.updating,
updateSuccess: storeState.featureFlagStore.updateSuccess,
getFeatureFlags: storeState.featureFlagStore.getEntities,
getEntity: storeState.featureFlagStore.getEntity,
updateEntity: storeState.featureFlagStore.updateEntity,
createEntity: storeState.featureFlagStore.createEntity,
reset: storeState.featureFlagStore.reset,
});

type StoreProps = ReturnType<typeof mapStoreToProps>;

export default connect(mapStoreToProps)(FeatureFlagUpdate);
13 changes: 13 additions & 0 deletions src/main/webapp/app/entities/feature-flag/feature-flag.store.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { IFeatureFlag } from 'app/shared/model/feature-flag.model';
import { IRootStore } from 'app/stores';
import CrudStore from 'app/shared/util/crud-store';
import { ENTITY_TYPE } from 'app/config/constants/constants';
import { getEntityResourcePath } from 'app/shared/util/RouteUtils';

export class FeatureFlagStore extends CrudStore<IFeatureFlag> {
constructor(protected rootStore: IRootStore) {
super(rootStore, getEntityResourcePath(ENTITY_TYPE.FEATURE_FLAG));
}
}

export default FeatureFlagStore;
Loading

0 comments on commit 99c6d5a

Please sign in to comment.