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
8 changes: 8 additions & 0 deletions Composer/packages/client/src/pages/notifications/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,14 @@ export abstract class Notification implements INotification {
}
}

export class ServerNotification extends Notification {
type = NotificationType.GENERAL;
constructor(projectId: string, id: string, location: string, diagnostic: Diagnostic) {
super(projectId, id, location, diagnostic);
this.message = diagnostic.message;
}
}

export class DialogNotification extends Notification {
type = NotificationType.DIALOG;
constructor(projectId: string, id: string, location: string, diagnostic: Diagnostic) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@ import { useContext, useMemo } from 'react';

import { StoreContext } from '../../store';

import { Notification, DialogNotification, LuNotification, LgNotification } from './types';
import { Notification, DialogNotification, LuNotification, LgNotification, ServerNotification } from './types';
import { getReferredFiles } from './../../utils/luUtil';
export default function useNotifications(filter?: string) {
const { state } = useContext(StoreContext);
const { dialogs, luFiles, lgFiles, projectId } = state;
const { dialogs, luFiles, lgFiles, projectId, diagnostics } = state;
const memoized = useMemo(() => {
const notifactions: Notification[] = [];
diagnostics.forEach(d => {
notifactions.push(new ServerNotification(projectId, '', d.source, d));
});
dialogs.forEach(dialog => {
dialog.diagnostics.map(diagnostic => {
const location = `${dialog.id}.dialog`;
Expand All @@ -31,7 +34,7 @@ export default function useNotifications(filter?: string) {
});
});
return notifactions;
}, [dialogs, luFiles, lgFiles, projectId]);
}, [dialogs, luFiles, lgFiles, projectId, diagnostics]);

const notifications: Notification[] = filter ? memoized.filter(x => x.severity === filter) : memoized;
return notifications;
Expand Down
1 change: 1 addition & 0 deletions Composer/packages/client/src/store/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ export const initialState: State = {
location: '', // the path to the bot project
botEnvironment: 'production',
locale: 'en-us',
diagnostics: [],
botEndpoints: {},
remoteEndpoints: {},
focusPath: '', // the data path for PropertyEditor
Expand Down
3 changes: 2 additions & 1 deletion Composer/packages/client/src/store/reducer/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ const initLuFilesStatus = (botName: string, luFiles: LuFile[], dialogs: DialogIn
};

const getProjectSuccess: ReducerFunc = (state, { response }) => {
const { files, botName, botEnvironment, location, schemas, settings, id, locale } = response.data;
const { files, botName, botEnvironment, location, schemas, settings, id, locale, diagnostics } = response.data;
schemas.sdk.content = processSchema(id, schemas.sdk.content);
const { dialogs, luFiles, lgFiles, skillManifestFiles } = indexer.index(files, botName, schemas.sdk.content, locale);
state.projectId = id;
Expand All @@ -96,6 +96,7 @@ const getProjectSuccess: ReducerFunc = (state, { response }) => {
state.luFiles = initLuFilesStatus(botName, luFiles, dialogs);
state.settings = settings;
state.locale = locale;
state.diagnostics = diagnostics;
state.skillManifests = skillManifestFiles;
refreshLocalStorage(botName, state.settings);
mergeLocalStorage(botName, state.settings);
Expand Down
13 changes: 12 additions & 1 deletion Composer/packages/client/src/store/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,17 @@
// TODO: remove this once we can expand the types
/* eslint-disable @typescript-eslint/no-explicit-any */
import React from 'react';
import { PromptTab, BotSchemas, ProjectTemplate, DialogInfo, LgFile, LuFile, Skill, UserSettings } from '@bfc/shared';
import {
PromptTab,
BotSchemas,
ProjectTemplate,
DialogInfo,
LgFile,
LuFile,
Skill,
UserSettings,
Diagnostic,
} from '@bfc/shared';
import { JSONSchema7 } from '@bfc/extension';

import { AppUpdaterStatus, CreationFlowStatus, BotStatus } from '../constants';
Expand Down Expand Up @@ -84,6 +94,7 @@ export interface State {
location: string;
botEnvironment: string;
locale: string;
diagnostics: Diagnostic[];
botEndpoints: { [key: string]: string };
remoteEndpoints: { [key: string]: string };
/** the data path for PropertyEditor */
Expand Down
17 changes: 11 additions & 6 deletions Composer/packages/server/src/models/bot/botProject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import fs from 'fs';

import axios from 'axios';
import { autofixReferInDialog } from '@bfc/indexers';
import { getNewDesigner, FileInfo, Skill } from '@bfc/shared';
import { getNewDesigner, FileInfo, Skill, Diagnostic } from '@bfc/shared';
import { UserIdentity } from '@bfc/plugin-loader';

import { Path } from '../../utility/path';
Expand Down Expand Up @@ -67,6 +67,7 @@ export class BotProject {
[key: string]: string;
};
public skills: Skill[] = [];
public diagnostics: Diagnostic[] = [];
public settingManager: ISettingManager;
public settings: DialogSetting | null = null;
constructor(ref: LocationRef, user?: UserIdentity) {
Expand All @@ -84,6 +85,7 @@ export class BotProject {
}

public init = async () => {
this.diagnostics = [];
// those 2 migrate methods shall be removed after a period of time
await this._reformProjectStructure();
try {
Expand All @@ -92,7 +94,9 @@ export class BotProject {
// when re-index opened bot, file write may error
}
this.settings = await this.getEnvSettings('', false);
this.skills = await extractSkillManifestUrl(this.settings?.skill || []);
const { skillsParsed, diagnostics } = await extractSkillManifestUrl(this.settings?.skill || []);
this.skills = skillsParsed;
this.diagnostics.push(...diagnostics);
this.files = await this._getFiles();
};

Expand All @@ -104,6 +108,7 @@ export class BotProject {
location: this.dir,
schemas: this.getSchemas(),
skills: this.skills,
diagnostics: this.diagnostics,
settings: this.settings,
};
};
Expand Down Expand Up @@ -138,15 +143,15 @@ export class BotProject {
// update skill in settings
public updateSkill = async (config: Skill[]) => {
const settings = await this.getEnvSettings('', false);
const skills = await extractSkillManifestUrl(config);
const { skillsParsed } = await extractSkillManifestUrl(config);

settings.skill = skills.map(({ manifestUrl, name }) => {
settings.skill = skillsParsed.map(({ manifestUrl, name }) => {
return { manifestUrl, name };
});
await this.settingManager.set('', settings);

this.skills = skills;
return skills;
this.skills = skillsParsed;
return skillsParsed;
};

public exportToZip = cb => {
Expand Down
22 changes: 17 additions & 5 deletions Composer/packages/server/src/models/bot/skillManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import get from 'lodash/get';
import * as msRest from '@azure/ms-rest-js';
import { Skill } from '@bfc/shared';
import { Skill, Diagnostic, DiagnosticSeverity } from '@bfc/shared';

import logger from './../../logger';

Expand Down Expand Up @@ -46,12 +46,24 @@ export const getSkillByUrl = async (url: string, name?: string): Promise<Skill>
}
};

export const extractSkillManifestUrl = async (skills: any[]): Promise<Skill[]> => {
export const extractSkillManifestUrl = async (
skills: any[]
): Promise<{ skillsParsed: Skill[]; diagnostics: Diagnostic[] }> => {
const skillsParsed: Skill[] = [];
const diagnostics: Diagnostic[] = [];
for (const skill of skills) {
const { manifestUrl, name } = skill;
const parsedSkill = await getSkillByUrl(manifestUrl, name);
skillsParsed.push(parsedSkill);
try {
const parsedSkill = await getSkillByUrl(manifestUrl, name);
skillsParsed.push(parsedSkill);
} catch (error) {
const notify = new Diagnostic(
`Accessing skill manifest url error, ${manifestUrl}`,
'appsettings.json',
DiagnosticSeverity.Error
);
diagnostics.push(notify);
}
}
return skillsParsed;
return { skillsParsed, diagnostics };
};