Skip to content

Commit

Permalink
Merge pull request #478 from dulithsenanayake/custom-prop-feature
Browse files Browse the repository at this point in the history
[RRT] Add UI implementation for mandatory custom properties support feature
  • Loading branch information
dulithsenanayake authored Jun 30, 2023
2 parents a6fdd8d + 32f9c01 commit ac5a09f
Show file tree
Hide file tree
Showing 5 changed files with 483 additions and 211 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import APICreateBase from 'AppComponents/Apis/Create/Components/APICreateBase';
import DefaultAPIForm from 'AppComponents/Apis/Create/Components/DefaultAPIForm';
import APIProduct from 'AppData/APIProduct';
import AuthManager from 'AppData/AuthManager';
import Progress from 'AppComponents/Shared/Progress';


const getPolicies = async () => {
Expand Down Expand Up @@ -70,6 +71,7 @@ function APICreateDefault(props) {

const [isRevisioning, setIsRevisioning] = useState(false);
const [isDeploying, setIsDeploying] = useState(false);
const [isMandatoryPropsConfigured, setIsMandatoryPropsConfigured] = useState(false);
const [isPublishButtonClicked, setIsPublishButtonClicked] = useState(false);
/**
*
Expand Down Expand Up @@ -118,6 +120,18 @@ function APICreateDefault(props) {
});
}

const getDefaultCustomProperties = () => {
if (settings != null) {
if (settings.customProperties && settings.customProperties.length > 0 ) {
setIsMandatoryPropsConfigured(true);
}
}
};

useEffect(() => {
getDefaultCustomProperties();
}, [settings]);

/**
*
*
Expand Down Expand Up @@ -393,6 +407,12 @@ function APICreateDefault(props) {
);
}

if (isLoading) {
return (
<Progress />
)
}

return (
<APICreateBase title={pageTitle}>
<Grid container direction='row' justify='center' alignItems='center' spacing={3}>
Expand All @@ -419,7 +439,7 @@ function APICreateDefault(props) {
)}
</Grid>
<Grid item md={1} xs={0} />
<Grid item md={11} xs={12}>
<Grid item md={11} xs={12} data-testid='default-api-form'>

<DefaultAPIForm
onValidate={handleOnValidate}
Expand All @@ -445,7 +465,7 @@ function APICreateDefault(props) {
{isCreating && !isPublishButtonClicked && <CircularProgress size={24} />}
</Button>
</Grid>
{!AuthManager.isNotPublisher() && (
{!isMandatoryPropsConfigured && !AuthManager.isNotPublisher() && (
<Grid item>
<Button
id='itest-id-apicreatedefault-createnpublish'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ afterAll(() => server.close());
describe('Create REST API From scratch', () => {
test('Should render REST API from scratch form', async () => {
render(<APICreateDefault />);
expect(await screen.findByTestId('loading-publisher-settings')).toBeInTheDocument();
expect(await screen.findByTestId('default-api-form')).toBeInTheDocument();
expect(screen.getByRole('heading', {
name: /create an api/i,
})).toBeInTheDocument();
Expand All @@ -40,13 +40,14 @@ describe('Create REST API From scratch', () => {

test('Should have auto focused `Name` input field', async () => {
render(<APICreateDefault />);
expect(await screen.findByTestId('default-api-form')).toBeInTheDocument();
expect(screen.getByRole('textbox', { name: /name \*/i })).toHaveFocus();
userEvent.tab();
});

test('Should validate name field for empty and special characters', async () => {
render(<APICreateDefault />);
expect(await screen.findByTestId('loading-publisher-settings')).toBeInTheDocument();
expect(await screen.findByTestId('default-api-form')).toBeInTheDocument();
const NAME_INPUT = screen.getByRole('textbox', { name: /name \*/i });
const NAME_EMPTY_ERROR = /name should not be empty/i;
const VALID_API_NAME = 'sampleAPIName';
Expand Down Expand Up @@ -79,7 +80,9 @@ describe('Create REST API From scratch', () => {

test('should not exceed 50 character length', async () => {
render(<APICreateDefault />);
expect(screen.getByTestId('loading-publisher-settings')).toBeInTheDocument();
await waitFor(() => {
expect(screen.getByTestId('default-api-form')).toBeInTheDocument();
});
const NAME_INPUT = screen.getByRole('textbox', { name: /name \*/i });
const NAME_EXCEEDED_ERROR = /Name has exceeded the maximum number of 50 characters/i;
userEvent.type(NAME_INPUT, 'a'.repeat(50));
Expand All @@ -97,6 +100,7 @@ describe('Create REST API From scratch', () => {

test('Should validate context field for empty and special characters', async () => {
render(<APICreateDefault />);
expect(await screen.findByTestId('default-api-form')).toBeInTheDocument();
const CONTEXT_INPUT = screen.getByRole('textbox', { name: /context \*/i });
const CONTEXT_EMPTY_ERROR = /Context should not be empty/i;
const VALID_API_CONTEXT = 'sampleContext';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ export default function CheckboxLabels(props) {
const classes = useStyles();
const {
api, isMutualSSLEnabled, isCertAvailable, isAppLayerSecurityMandatory, isBusinessPlanAvailable, isAPIProduct,
isMandatoryPropertiesAvailable, isMandatoryPropertiesConfigured
} = props;
const isEndpointAvailable = !isAPIProduct
? api.endpointConfig !== null && !api.endpointConfig.implementation_status
Expand Down Expand Up @@ -172,6 +173,24 @@ export default function CheckboxLabels(props) {
</Link>
</Grid>
) }
{isMandatoryPropertiesConfigured && (
<Grid xs={12} className={classes.grid}>
{isMandatoryPropertiesAvailable ? (
<CheckIcon className={classes.iconTrue} />
) : (
<CloseIcon className={classes.iconFalse} />
)}
<Typography>
<FormattedMessage
id='Apis.Details.LifeCycle.CheckboxLabels.mandatory.properties.provided'
defaultMessage='Mandatory Properties provided'
/>
</Typography>
<Link to={'/apis/' + api.id + '/properties'} aria-label='Properties'>
<LaunchIcon style={{ marginLeft: '2px' }} color='primary' fontSize='small' />
</Link>
</Grid>
)}
</>
</Grid>
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import PublishWithoutDeploy from 'AppComponents/Apis/Details/LifeCycle/Component
import PublishWithoutDeployProduct from 'AppComponents/Apis/Details/LifeCycle/Components/PublishWithoutDeployProduct';
import Configurations from 'Config';
import APIProduct from 'AppData/APIProduct';
import Progress from 'AppComponents/Shared/Progress';
import LifeCycleImage from './LifeCycleImage';
import CheckboxLabels from './CheckboxLabels';
import LifecyclePending from './LifecyclePending';
Expand Down Expand Up @@ -93,22 +94,61 @@ class LifeCycleUpdate extends Component {
pageError: null,
isOpen: false,
deploymentsAvailable: false,
isMandatoryPropertiesAvailable: false,
loading: true,
isMandatoryPropertiesConfigured: false,
};
this.setIsOpen = this.setIsOpen.bind(this);
this.handleClick = this.handleClick.bind(this);
}

/**
*
* Set Deployment availability
* Set Deployment & Mandatory Properties availability
*/
componentDidMount() {
this.fetchData();
}

fetchData() {
const {
api: { id: apiUUID },
} = this.props;
this.api.getRevisionsWithEnv(apiUUID).then((result) => {
this.setState({ deploymentsAvailable: result.body.count > 0 });
});
const { api } = this.context;

this.api.getRevisionsWithEnv(apiUUID)
.then((result) => {
this.setState({ deploymentsAvailable: result.body.count > 0 });
api.getSettings()
.then((response) => {
const { customProperties } = response;
let isMandatoryPropertiesAvailable;
if (customProperties && customProperties.length > 0) {
const requiredPropertyNames = customProperties
.filter(property => property.Required)
.map(property => property.Name);
if (requiredPropertyNames.length > 0) {
this.setState({ isMandatoryPropertiesConfigured: true })
isMandatoryPropertiesAvailable = requiredPropertyNames.every(propertyName => {
const property = api.additionalProperties.find(prop => prop.name === propertyName);
return property && property.value !== '';
});
} else {
isMandatoryPropertiesAvailable = true;
}
} else {
isMandatoryPropertiesAvailable = true;
}
this.setState({ isMandatoryPropertiesAvailable });
this.setState({ loading: false });
})
.catch((error) => {
console.error('Error fetching settings:', error);
});
})
.catch((error) => {
console.error('Error fetching revisions:', error);
});
}

/**
Expand Down Expand Up @@ -226,7 +266,8 @@ class LifeCycleUpdate extends Component {
api, lcState, classes, theme, handleChangeCheckList, checkList, certList, isAPIProduct,
} = this.props;
const lifecycleStates = [...lcState.availableTransitions];
const { newState, pageError, isOpen, deploymentsAvailable } = this.state;
const { newState, pageError, isOpen, deploymentsAvailable, isMandatoryPropertiesAvailable,
isMandatoryPropertiesConfigured } = this.state;
const isWorkflowPending = api.workflowStatus && api.workflowStatus === this.WORKFLOW_STATUS.CREATED;
const lcMap = new Map();
lcMap.set('Published', 'Publish');
Expand Down Expand Up @@ -257,7 +298,8 @@ class LifeCycleUpdate extends Component {
if (lifecycleState.event === 'Publish') {
const buttonDisabled = (isMutualSSLEnabled && !isCertAvailable)
|| (deploymentsAvailable && !isBusinessPlanAvailable)
|| (isAPIProduct && !isBusinessPlanAvailable);
|| (isAPIProduct && !isBusinessPlanAvailable)
|| (deploymentsAvailable && !isMandatoryPropertiesAvailable);
// When business plans are not assigned and deployments available

return {
Expand All @@ -271,6 +313,12 @@ class LifeCycleUpdate extends Component {
};
});

if (this.state.loading) {
return (
<Progress />
)
}

return (
<Grid container>
{isWorkflowPending ? (
Expand Down Expand Up @@ -299,6 +347,8 @@ class LifeCycleUpdate extends Component {
isCertAvailable={isCertAvailable}
isBusinessPlanAvailable={isBusinessPlanAvailable}
isAPIProduct={isAPIProduct}
isMandatoryPropertiesAvailable={isMandatoryPropertiesAvailable}
isMandatoryPropertiesConfigured={isMandatoryPropertiesConfigured}
/>
</Grid>
)}
Expand Down
Loading

0 comments on commit ac5a09f

Please sign in to comment.