Skip to content
This repository was archived by the owner on Jul 9, 2025. It is now read-only.
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
3 changes: 0 additions & 3 deletions Composer/cypress/integration/NotificationPage.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,6 @@ context('Notification Page', () => {
it('can show dialog expression error ', () => {
cy.visitPage('Design');

// click the logo to clear any stray tooltips from page navigation
cy.findByAltText('Composer Logo').click();

cy.findByTestId('ProjectTree').within(() => {
cy.findByText('WelcomeUser').click();
});
Expand Down
3 changes: 3 additions & 0 deletions Composer/cypress/support/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ Cypress.Commands.add('withinEditor', (editorName, cb) => {
Cypress.Commands.add('visitPage', (page) => {
cy.findByTestId(`LeftNav-CommandBarButton${page}`).click();
cy.findByTestId('ActiveLeftNavItem').should('contain', page);

// click the logo to clear any stray tooltips from page navigation
cy.findByAltText('Composer Logo').click({ force: true });
});

Cypress.Commands.add('enterTextAndSubmit', (textElement: string, text: string, submitBtn?: string) => {
Expand Down
4 changes: 4 additions & 0 deletions Composer/packages/client/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,10 @@ export enum ActionTypes {
REMOVE_SKILL_MANIFEST = 'REMOVE_SKILL_MANIFEST',
DISPLAY_SKILL_MANIFEST_MODAL = 'DISPLAY_SKILL_MANIFEST_MODAL',
DISMISS_SKILL_MANIFEST_MODAL = 'DISMISS_SKILL_MANIFEST_MODAL',
SET_PUBLISH_TARGETS = 'SET_PUBLISH_TARGETS',
SET_RUNTIME_SETTINGS = 'SET_RUNTIME_SETTINGS',
SET_CUSTOM_RUNTIME_TOGGLE = 'SET_CUSTOM_RUNTIME_TOGGLE',
SET_RUNTIME_FIELD = 'SET_RUNTIME_FIELD',
}

export const Tips = {
Expand Down
12 changes: 6 additions & 6 deletions Composer/packages/client/src/pages/publish/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -221,14 +221,14 @@ const Publish: React.FC<PublishPageProps> = (props) => {

const savePublishTarget = useCallback(
async (name: string, type: string, configuration: string) => {
const target = (settings.publishTargets || []).concat([
const targets = (settings.publishTargets || []).concat([
{
name,
type,
configuration,
},
]);
await actions.setSettings(projectId, { ...settings, publishTargets: target });
await actions.setPublishTargets(targets);
onSelectTarget(name);
},
[settings.publishTargets, projectId, botName]
Expand All @@ -248,7 +248,7 @@ const Publish: React.FC<PublishPageProps> = (props) => {
configuration,
};

await actions.setSettings(projectId, { ...settings, publishTargets: targets });
await actions.setPublishTargets(targets);

onSelectTarget(name);
},
Expand Down Expand Up @@ -314,7 +314,7 @@ const Publish: React.FC<PublishPageProps> = (props) => {
}
});

await actions.setSettings(projectId, { ...settings, publishTargets: updatedPublishTargets });
await actions.setPublishTargets(updatedPublishTargets);
}
},
[projectId, selectedTarget, settings.publishTargets]
Expand All @@ -339,8 +339,8 @@ const Publish: React.FC<PublishPageProps> = (props) => {

if (result) {
if (settings.publishTargets && settings.publishTargets.length > index) {
const target = settings.publishTargets.slice(0, index).concat(settings.publishTargets.slice(index + 1));
await actions.setSettings(projectId, { ...settings, publishTargets: target });
const targets = settings.publishTargets.slice(0, index).concat(settings.publishTargets.slice(index + 1));
await actions.setPublishTargets(targets);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @beyackle I found the action use setPublishTarget, use setPublishTarget[s] will throw error. And the arguments is ( _, publishTarget).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I fixed these in #3550

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for taking care of that.

// redirect to all profiles
setSelectedTarget(undefined);
onSelectTarget('all');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,7 @@ export const DialogSettings: React.FC<RouteComponentProps> = () => {

const saveChangeResult = (result) => {
try {
const mergedResult = result;
actions.setSettings(projectId, mergedResult);
actions.setSettings(projectId, result);
} catch (err) {
// eslint-disable-next-line no-console
console.error(err.message);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,13 @@ import { breathingSpace, runtimeSettingsStyle, runtimeControls, runtimeToggle, c

export const RuntimeSettings: React.FC<RouteComponentProps> = () => {
const { state, actions } = useContext(StoreContext);
const { setCustomRuntime, setRuntimeField } = actions;
const { botName, settings, projectId } = state;
const [formDataErrors, setFormDataErrors] = useState({ command: '', path: '' });
const [ejectModalVisible, setEjectModalVisible] = useState(false);

const changeEnabled = (_, on) => {
actions.setSettings(projectId, { ...settings, runtime: { ...settings.runtime, customRuntime: on } });
const handleChangeToggle = (_, isOn = false) => {
setCustomRuntime(projectId, isOn);
};

const updateSetting = (field) => (e, newValue) => {
Expand All @@ -34,7 +35,7 @@ export const RuntimeSettings: React.FC<RouteComponentProps> = () => {
error = 'This is a required field.';
}

actions.setSettings(projectId, { ...settings, runtime: { ...settings.runtime, [field]: newValue } });
setRuntimeField(projectId, field, newValue);

if (valid) {
setFormDataErrors({ ...formDataErrors, [field]: '' });
Expand All @@ -53,9 +54,9 @@ export const RuntimeSettings: React.FC<RouteComponentProps> = () => {
<div css={runtimeToggle}>
<Toggle
inlineLabel
checked={settings.runtime && settings.runtime.customRuntime === true}
checked={settings.runtime?.customRuntime}
label={formatMessage('Use custom runtime')}
onChange={changeEnabled}
onChange={handleChangeToggle}
/>
</div>
);
Expand Down
17 changes: 4 additions & 13 deletions Composer/packages/client/src/store/action/eject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { ActionCreator } from '../types';
import { ActionTypes } from '../../constants';

import httpClient from './../../utils/httpUtil';
import { setSettings } from './setting';
import { setRuntimeSettings } from './setting';

export const getRuntimeTemplates: ActionCreator = async ({ dispatch }) => {
try {
Expand All @@ -23,24 +23,15 @@ export const getRuntimeTemplates: ActionCreator = async ({ dispatch }) => {
};

export const ejectRuntime: ActionCreator = async (store, projectId, name) => {
const { dispatch, getState } = store;
const { dispatch } = store;
try {
const response = await httpClient.post(`/runtime/eject/${projectId}/${name}`);
dispatch({
type: ActionTypes.EJECT_SUCCESS,
payload: response.data,
});
if (response.data.settings && response.data.settings.path) {
const { settings: oldsettings } = getState();
setSettings(store, projectId, {
...oldsettings,
runtime: {
...oldsettings.runtime,
customRuntime: true,
path: response.data.settings.path,
command: response.data.settings.startCommand,
},
});
if (response.data.settings?.path) {
setRuntimeSettings(store, projectId, response.data.settings.path, response.data.settings.startCommand);
}
} catch (err) {
dispatch({
Expand Down
39 changes: 39 additions & 0 deletions Composer/packages/client/src/store/action/setting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,42 @@ export const setSettings: ActionCreator = async ({ dispatch }, projectId: string
},
});
};

export const setPublishTarget: ActionCreator = async ({ dispatch }, _, publishTarget) => {
dispatch({
type: ActionTypes.SET_PUBLISH_TARGETS,
payload: {
publishTarget,
},
});
};

export const setRuntimeSettings: ActionCreator = async ({ dispatch }, projectId: string, path, command) => {
dispatch({
type: ActionTypes.SET_RUNTIME_SETTINGS,
payload: {
projectId,
path,
command,
},
});
};

export const setCustomRuntime: ActionCreator = async ({ dispatch }, _, isOn) => {
dispatch({
type: ActionTypes.SET_CUSTOM_RUNTIME_TOGGLE,
payload: {
isOn,
},
});
};

export const setRuntimeField: ActionCreator = async ({ dispatch }, _, field, newValue) => {
dispatch({
type: ActionTypes.SET_RUNTIME_FIELD,
payload: {
field,
newValue,
},
});
};
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ const actionType2ChangeType = {
[ActionTypes.REMOVE_SKILL_MANIFEST]: { changeType: ChangeType.DELETE, fileExtension: FileExtensions.Manifest },
[ActionTypes.UPDATE_SKILL_MANIFEST]: { changeType: ChangeType.UPDATE, fileExtension: FileExtensions.Manifest },
[ActionTypes.SYNC_ENV_SETTING]: { changeType: ChangeType.UPDATE, fileExtension: FileExtensions.Setting },
[ActionTypes.SET_PUBLISH_TARGETS]: { changeType: ChangeType.UPDATE, fileExtension: FileExtensions.Setting },
[ActionTypes.SET_RUNTIME_SETTINGS]: { changeType: ChangeType.UPDATE, fileExtension: FileExtensions.Setting },
};

class FilePersistence {
Expand Down
32 changes: 30 additions & 2 deletions Composer/packages/client/src/store/reducer/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ const saveTemplateId: ReducerFunc = (state, { templateId }) => {

const setError: ReducerFunc = (state, payload) => {
// if the error originated at the server and the server included message, use it...
if (payload && payload.status && payload.status === 409) {
if (payload?.status === 409) {
state.error = {
status: 409,
message: formatMessage(
Expand All @@ -351,7 +351,7 @@ const setError: ReducerFunc = (state, payload) => {
summary: formatMessage('Modification Rejected'),
};
} else {
if (payload && payload.response && payload.response.data && payload.response.data.message) {
if (payload?.response?.data?.message) {
state.error = payload.response.data;
} else {
state.error = payload;
Expand Down Expand Up @@ -447,6 +447,30 @@ const syncEnvSetting: ReducerFunc = (state, { settings, projectId }) => {
return state;
};

const setPublishTargets: ReducerFunc = (state, { publishTarget }) => {
state.publishTargets = publishTarget;
return state;
};

const setRuntimeSettings: ReducerFunc = (state, { path, command }) => {
state.settings.runtime = {
customRuntime: true,
path,
command,
};
return state;
};

const setRuntimeField: ReducerFunc = (state, { field, newValue }) => {
if (state.settings.runtime != null) state.settings.runtime[field] = newValue;
return state;
};

const setCustomRuntimeToggle: ReducerFunc = (state, { isOn }) => {
setRuntimeField(state, { field: 'customRuntime', newValue: isOn });
return state;
};

const setTemplateProjects: ReducerFunc = (state, { response } = {}) => {
const data = response && response.data;

Expand Down Expand Up @@ -702,4 +726,8 @@ export const reducer = createReducer({
[ActionTypes.SET_APP_UPDATE_STATUS]: setAppUpdateStatus,
[ActionTypes.DISPLAY_SKILL_MANIFEST_MODAL]: displaySkillManifestModal,
[ActionTypes.DISMISS_SKILL_MANIFEST_MODAL]: dismissSkillManifestModal,
[ActionTypes.SET_PUBLISH_TARGETS]: setPublishTargets,
[ActionTypes.SET_RUNTIME_SETTINGS]: setRuntimeSettings,
[ActionTypes.SET_CUSTOM_RUNTIME_TOGGLE]: setCustomRuntimeToggle,
[ActionTypes.SET_RUNTIME_FIELD]: setRuntimeField,
});
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ describe('get bot project', () => {
await ProjectController.getProjectById(mockReq, mockRes);
expect(mockRes.status).toHaveBeenCalledWith(404);
expect(mockRes.json).toHaveBeenCalledWith({
message: 'project not found in cache',
message: 'project undefined not found in cache',
});
});

Expand Down Expand Up @@ -121,7 +121,7 @@ describe('open bot operation', () => {
await ProjectController.openProject(mockReq, mockRes);
expect(mockRes.status).toHaveBeenCalledWith(400);
expect(mockRes.json).toHaveBeenCalledWith({
message: 'file not exist wrong/path',
message: 'file wrong/path does not exist',
});
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,10 @@ afterAll(() => {
describe('test BotProjectService', () => {
it('openProject', async () => {
const projectId = await BotProjectService.openProject(location1);
await expect(BotProjectService.getProjectById('123')).rejects.toThrowError('project not found in cache');
const otherId = '12345.678';
await expect(BotProjectService.getProjectById(otherId)).rejects.toThrowError(
`project ${otherId} not found in cache`
);
expect((await BotProjectService.getProjectById(projectId)).dir).toBe(projPath);
});

Expand Down
11 changes: 6 additions & 5 deletions Composer/packages/server/src/services/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ export class BotProjectService {
// TODO: this should be refactored or moved into the BotProject constructor so that it can use user auth amongst other things
if (!(await StorageService.checkBlob(locationRef.storageId, locationRef.path, user))) {
BotProjectService.deleteRecentProject(locationRef.path);
throw new Error(`file not exist ${locationRef.path}`);
throw new Error(`file ${locationRef.path} does not exist`);
}

for (const key in BotProjectService.projectLocationMap) {
Expand Down Expand Up @@ -209,15 +209,16 @@ export class BotProjectService {
public static getProjectById = async (projectId: string, user?: UserIdentity): Promise<BotProject> => {
BotProjectService.initialize();

if (!BotProjectService.projectLocationMap?.[projectId]) {
throw new Error('project not found in cache');
const path = BotProjectService.projectLocationMap[projectId];

if (path == null) {
throw new Error(`project ${projectId} not found in cache`);
} else {
const path = BotProjectService.projectLocationMap[projectId];
// check to make sure the project is still there!
if (!(await StorageService.checkBlob('default', path, user))) {
BotProjectService.deleteRecentProject(path);
BotProjectService.removeProjectIdFromCache(projectId);
throw new Error(`file not exist ${path}`);
throw new Error(`file ${path} does not exist`);
}
const project = new BotProject({ storageId: 'default', path: path }, user);
await project.init();
Expand Down