Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RRT] Add UI implementation for mandatory custom properties support feature #478

Merged
merged 5 commits into from
Jun 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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