diff --git a/addons/addon-base-raas-ui/packages/base-raas-ui/src/models/projects/Project.js b/addons/addon-base-raas-ui/packages/base-raas-ui/src/models/projects/Project.js
index ebbc05edf3..cf79a9f174 100644
--- a/addons/addon-base-raas-ui/packages/base-raas-ui/src/models/projects/Project.js
+++ b/addons/addon-base-raas-ui/packages/base-raas-ui/src/models/projects/Project.js
@@ -30,6 +30,7 @@ const Project = types
updatedAt: '',
updatedBy: '',
projectAdmins: types.optional(types.array(types.string), []),
+ isAppStreamConfigured: types.optional(types.boolean, false),
})
.actions(self => ({
setProject(rawProject) {
diff --git a/addons/addon-base-raas-ui/packages/base-raas-ui/src/parts/environments-sc/ScEnvironmentsList.js b/addons/addon-base-raas-ui/packages/base-raas-ui/src/parts/environments-sc/ScEnvironmentsList.js
index cc073017cb..4f445a7ab0 100644
--- a/addons/addon-base-raas-ui/packages/base-raas-ui/src/parts/environments-sc/ScEnvironmentsList.js
+++ b/addons/addon-base-raas-ui/packages/base-raas-ui/src/parts/environments-sc/ScEnvironmentsList.js
@@ -25,6 +25,7 @@ import ScEnvironmentsFilterButtons from './parts/ScEnvironmentsFilterButtons';
// expected props
// - scEnvironmentsStore (via injection)
// - envTypesStore (via injection)
+// - projectsStore (via injection)
class ScEnvironmentsList extends React.Component {
constructor(props) {
super(props);
@@ -33,6 +34,7 @@ class ScEnvironmentsList extends React.Component {
const name = storage.getItem(key) || filterNames.ALL;
storage.setItem(key, name);
this.selectedFilter = name;
+ this.provisionDisabled = false;
});
}
@@ -53,6 +55,10 @@ class ScEnvironmentsList extends React.Component {
store.stopHeartbeat();
}
+ get isAppStreamEnabled() {
+ return process.env.REACT_APP_IS_APP_STREAM_ENABLED === 'true';
+ }
+
get envTypesStore() {
return this.props.envTypesStore;
}
@@ -61,6 +67,17 @@ class ScEnvironmentsList extends React.Component {
return this.props.scEnvironmentsStore;
}
+ getProjects() {
+ const store = this.getProjectsStore();
+ return store.list;
+ }
+
+ getProjectsStore() {
+ const store = this.props.projectsStore;
+ store.load();
+ return store;
+ }
+
handleCreateEnvironment = event => {
event.preventDefault();
event.stopPropagation();
@@ -78,6 +95,15 @@ class ScEnvironmentsList extends React.Component {
render() {
const store = this.envsStore;
let content = null;
+ const projects = this.getProjects();
+ const appStreamProjectIds = _.map(
+ _.filter(projects, proj => proj.isAppStreamConfigured),
+ 'id',
+ );
+
+ runInAction(() => {
+ if (this.isAppStreamEnabled && _.isEmpty(appStreamProjectIds)) this.provisionDisabled = true;
+ });
if (isStoreError(store)) {
content = ;
@@ -86,7 +112,7 @@ class ScEnvironmentsList extends React.Component {
} else if (isStoreEmpty(store)) {
content = this.renderEmpty();
} else if (isStoreNotEmpty(store)) {
- content = this.renderMain();
+ content = this.renderMain(appStreamProjectIds);
} else {
content = null;
}
@@ -94,15 +120,34 @@ class ScEnvironmentsList extends React.Component {
return (
{this.renderTitle()}
+ {this.provisionDisabled && this.renderMissingAppStreamConfig()}
{content}
);
}
- renderMain() {
+ renderMissingAppStreamConfig() {
+ return (
+ <>
+
+
+
+ Missing association with AppStream projects
+
+ Since your projects are not associated to an AppStream-configured account, creating a new workspace is
+ disabled. Please contact your administrator.
+
+
+
+ >
+ );
+ }
+
+ renderMain(appStreamProjectIds) {
const store = this.envsStore;
const selectedFilter = this.selectedFilter;
- const list = store.filtered(selectedFilter);
+ let list = store.filtered(selectedFilter);
+ list = this.isAppStreamEnabled ? _.filter(list, env => _.includes(appStreamProjectIds, env.projectId)) : list;
const isEmpty = _.isEmpty(list);
return (
@@ -155,6 +200,7 @@ class ScEnvironmentsList extends React.Component {
data-testid="create-workspace"
color="blue"
size="medium"
+ disabled={this.provisionDisabled}
basic
onClick={this.handleCreateEnvironment}
>
@@ -176,10 +222,15 @@ class ScEnvironmentsList extends React.Component {
// see https://medium.com/@mweststrate/mobx-4-better-simpler-faster-smaller-c1fbc08008da
decorate(ScEnvironmentsList, {
selectedFilter: observable,
+ provisionDisabled: observable,
envsStore: computed,
envTypesStore: computed,
handleCreateEnvironment: action,
handleSelectedFilter: action,
});
-export default inject('scEnvironmentsStore', 'envTypesStore')(withRouter(observer(ScEnvironmentsList)));
+export default inject(
+ 'scEnvironmentsStore',
+ 'projectsStore',
+ 'envTypesStore',
+)(withRouter(observer(ScEnvironmentsList)));
diff --git a/addons/addon-base-raas-ui/packages/base-raas-ui/src/parts/environments-sc/setup/CreateInternalEnvForm.js b/addons/addon-base-raas-ui/packages/base-raas-ui/src/parts/environments-sc/setup/CreateInternalEnvForm.js
index d6a28ca860..e05370d7d4 100644
--- a/addons/addon-base-raas-ui/packages/base-raas-ui/src/parts/environments-sc/setup/CreateInternalEnvForm.js
+++ b/addons/addon-base-raas-ui/packages/base-raas-ui/src/parts/environments-sc/setup/CreateInternalEnvForm.js
@@ -2,7 +2,7 @@ import _ from 'lodash';
import React from 'react';
import { decorate, computed, runInAction, observable, action } from 'mobx';
import { observer, inject } from 'mobx-react';
-import { Segment, Button, Header } from 'semantic-ui-react';
+import { Segment, Button, Header, Icon } from 'semantic-ui-react';
import { displayError } from '@aws-ee/base-ui/dist/helpers/notification';
import Dropdown from '@aws-ee/base-ui/dist/parts/helpers/fields/DropDown';
import Form from '@aws-ee/base-ui/dist/parts/helpers/fields/Form';
@@ -21,20 +21,37 @@ import SelectConfigurationCards from './SelectConfigurationCards';
// - defaultCidr (via props)
// - clientInformationStore (via injection)
// - userStore (via injection)
+// - projectsStore (via injection)
class CreateInternalEnvForm extends React.Component {
constructor(props) {
super(props);
runInAction(() => {
this.form = getCreateInternalEnvForm({
- projectIdOptions: this.projectIdOptions,
+ projectIdOptions: this.getProjectIdOptions(),
cidr: this.props.defaultCidr,
});
});
}
- get projectIdOptions() {
+ // The list of projects assigned to the user might be broader than the
+ // list of projects actually available for environment provisioning
+ // For example: Projects not fully configured with AppStream need to be filtered out
+ getProjectIdOptions() {
const store = this.userStore;
- return store.projectIdDropdown;
+ if (!this.isAppStreamEnabled) return store.projectIdDropdown;
+
+ const projects = this.getProjects();
+ const filteredProjects = _.filter(projects, proj => proj.isAppStreamConfigured);
+ if (_.isEmpty(filteredProjects)) return [];
+
+ const filteredProjectIds = _.map(filteredProjects, proj => proj.id);
+ const retVal = _.filter(store.projectIdDropdown, proj => _.includes(filteredProjectIds, proj.key));
+
+ return retVal;
+ }
+
+ get isAppStreamEnabled() {
+ return process.env.REACT_APP_IS_APP_STREAM_ENABLED === 'true';
}
get envTypeId() {
@@ -49,6 +66,17 @@ class CreateInternalEnvForm extends React.Component {
return this.props.userStore;
}
+ getProjects() {
+ const store = this.getProjectsStore();
+ return store.list;
+ }
+
+ getProjectsStore() {
+ const store = this.props.projectsStore;
+ store.load();
+ return store;
+ }
+
// eslint-disable-next-line consistent-return
handlePrevious = () => {
if (_.isFunction(this.props.onPrevious)) return this.props.onPrevious();
@@ -77,11 +105,59 @@ class CreateInternalEnvForm extends React.Component {
);
}
+ renderButtons() {
+ return (
+
+
+
+
+ );
+ }
+
+ renderMissingAppStreamConfig() {
+ return (
+ <>
+
+
+
+ Missing association with AppStream projects
+
+ Your projects are not associated to an AppStream-configured account. Please contact your administrator.
+
+
+
+ {this.renderButtons()}
+ >
+ );
+ }
+
renderForm() {
const form = this.form;
const askForCidr = !_.isUndefined(this.props.defaultCidr);
const configurations = this.configurations;
+ // we show the AppStream configuration warning when the feature is enabled,
+ // and the user's projects are not linked to AppStream-configured accounts
+ const projects = this.getProjectIdOptions();
+ if (this.isAppStreamEnabled && _.isEmpty(projects)) {
+ return this.renderMissingAppStreamConfig();
+ }
+
return (