* NEW: kb.gbapp now has a complete browser of excel articles.
* FIX: Some security improved. * NEW: Protocol changes for exchanging questions between UI and Bot Server.
This commit is contained in:
parent
708a27e419
commit
379ade60fb
10 changed files with 170 additions and 101 deletions
|
@ -107,7 +107,7 @@ export class AdminDialog extends IGBDialog {
|
|||
let importer = new GBImporter(min.core);
|
||||
let deployer = new GBDeployer(min.core, importer);
|
||||
|
||||
min.dialogs.add("/admin", [
|
||||
min.dialogs.add("/adminRat", [
|
||||
async dc => {
|
||||
await AdminDialog.refreshAdminToken(min, dc);
|
||||
// await dc.context.sendActivity(
|
||||
|
@ -137,7 +137,7 @@ export class AdminDialog extends IGBDialog {
|
|||
}
|
||||
]);
|
||||
|
||||
min.dialogs.add("/admin1", [
|
||||
min.dialogs.add("/admin", [
|
||||
async (dc, args) => {
|
||||
const prompt = "Please, authenticate:";
|
||||
await dc.prompt("textPrompt", prompt);
|
||||
|
|
|
@ -291,9 +291,9 @@ export class GBMinService {
|
|||
}
|
||||
|
||||
logger.info(
|
||||
`[RCV]: ${context.activity.type}, ChannelID: ${
|
||||
`[User]: ${context.activity.type}, ChannelID: ${
|
||||
context.activity.channelId
|
||||
}, Name: ${context.activity.name}, Text: ${context.activity.text}.`
|
||||
} Text: ${context.activity.text}.`
|
||||
)
|
||||
if (
|
||||
context.activity.type === "conversationUpdate" &&
|
||||
|
@ -358,9 +358,9 @@ export class GBMinService {
|
|||
})
|
||||
} else if (context.activity.name === "showFAQ") {
|
||||
await dc.begin("/faq")
|
||||
} else if (context.activity.name === "ask") {
|
||||
await dc.begin("/answer", {
|
||||
query: (context.activity as any).data,
|
||||
} else if (context.activity.name === "answerEvent") {
|
||||
await dc.begin("/answerEvent", {
|
||||
questionId: (context.activity as any).data,
|
||||
fromFaq: true
|
||||
})
|
||||
|
||||
|
@ -374,7 +374,7 @@ export class GBMinService {
|
|||
}
|
||||
}
|
||||
} catch (error) {
|
||||
let msg = `Error in main activity: ${error.message}`
|
||||
let msg = `Error in main activity: ${error.message} ${error.stack? error.stack:""}`
|
||||
logger.error(msg)
|
||||
}
|
||||
})
|
||||
|
|
|
@ -57,9 +57,11 @@ class GBUIApp extends React.Component {
|
|||
token: null,
|
||||
instanceClient: null
|
||||
};
|
||||
window.user = this.getUser()
|
||||
}
|
||||
|
||||
sendToken(token) {
|
||||
|
||||
setTimeout(() => {
|
||||
window.botConnection
|
||||
.postActivity({
|
||||
|
@ -69,7 +71,7 @@ class GBUIApp extends React.Component {
|
|||
locale: "en-us",
|
||||
textFormat: "plain",
|
||||
timestamp: new Date().toISOString(),
|
||||
from: { id: "webUser", name: "You" }
|
||||
from: this.getUser()
|
||||
})
|
||||
.subscribe(() => {
|
||||
window.userAgentApplication.logout();
|
||||
|
@ -86,10 +88,11 @@ class GBUIApp extends React.Component {
|
|||
locale: "en-us",
|
||||
textFormat: "plain",
|
||||
timestamp: new Date().toISOString(),
|
||||
from: { id: "webUser", name: "You" }
|
||||
from: this.getUser()
|
||||
})
|
||||
.subscribe(console.log("EVENT SENT TO Guaribas."));
|
||||
}
|
||||
|
||||
getUser() {
|
||||
return { id: "webUser@gb", name: "You" };
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ class SideBarMenu extends React.Component {
|
|||
locale: "en-us",
|
||||
textFormat: "plain",
|
||||
timestamp: new Date().toISOString(),
|
||||
from: { id: "webUser", name: "You" }
|
||||
from: window.user
|
||||
})
|
||||
.subscribe(console.log("success"));
|
||||
}
|
||||
|
|
|
@ -39,12 +39,12 @@ class RenderItem extends Component {
|
|||
window.botConnection
|
||||
.postActivity({
|
||||
type: "event",
|
||||
name: "ask",
|
||||
data: item.content,
|
||||
name: "answerEvent",
|
||||
data: item.questionId,
|
||||
locale: "en-us",
|
||||
textFormat: "plain",
|
||||
timestamp: new Date().toISOString(),
|
||||
from: { id: "webUser", name: "You" }
|
||||
from: window.user
|
||||
})
|
||||
.subscribe(console.log("success"));
|
||||
},400);
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
import React, { Component } from "react";
|
||||
|
||||
class GBMarkdownPlayer extends Component {
|
||||
|
||||
send(value) {
|
||||
setTimeout(() => {
|
||||
window.botConnection
|
||||
|
@ -49,15 +50,35 @@ class GBMarkdownPlayer extends Component {
|
|||
}, 400);
|
||||
}
|
||||
|
||||
sendAnswer(text) {
|
||||
setTimeout(() => {
|
||||
window.botConnection
|
||||
.postActivity({
|
||||
type: "event",
|
||||
name: "answerEvent",
|
||||
data: text,
|
||||
locale: "en-us",
|
||||
textFormat: "plain",
|
||||
timestamp: new Date().toISOString(),
|
||||
from: window.user
|
||||
})
|
||||
.subscribe(console.log("success"));
|
||||
}, 400);
|
||||
|
||||
}
|
||||
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.state = {
|
||||
content: ""
|
||||
content: "",
|
||||
prevId: 0,
|
||||
nextId: 0
|
||||
};
|
||||
}
|
||||
|
||||
play(data) {
|
||||
this.setState({ content: data });
|
||||
this.setState({ content: data.content, prevId: data.prevId, nextId: data.nextId });
|
||||
}
|
||||
|
||||
stop() {
|
||||
|
@ -78,7 +99,7 @@ class GBMarkdownPlayer extends Component {
|
|||
|
||||
render() {
|
||||
|
||||
var quality =
|
||||
var quality =
|
||||
<div className="gb-markdown-player-quality">
|
||||
<span ref={i => (this.quality = i)}>Is the answer OK?</span>
|
||||
|
||||
|
@ -91,18 +112,34 @@ class GBMarkdownPlayer extends Component {
|
|||
</button>
|
||||
</div>;
|
||||
|
||||
if (this.state.content === "") {
|
||||
quality = "";
|
||||
}
|
||||
var next = "", prev = "";
|
||||
|
||||
if (this.state.content === "") {
|
||||
quality = "";
|
||||
}
|
||||
|
||||
if (this.state.prevId) {
|
||||
prev = <a style={{ color: 'blue' }}
|
||||
onPress={() => this.sendAnswer(this.state.prevId)}>
|
||||
Back
|
||||
</a>
|
||||
}
|
||||
if (this.state.nextId) {
|
||||
next = <a style={{ color: 'blue' }}
|
||||
onPress={() => this.sendAnswer(this.state.nextId)}>
|
||||
Next
|
||||
</a>
|
||||
}
|
||||
|
||||
return (
|
||||
<div ref={i => (this.playerText = i)} className="media-player">
|
||||
<div className="media-player-container">
|
||||
<div className="media-player-scroll">
|
||||
<div><span>{prev}</span> <span>{next}</span></div>
|
||||
<span dangerouslySetInnerHTML={this.createMarkup()} />
|
||||
</div>
|
||||
</div>
|
||||
{quality}
|
||||
</div>
|
||||
{quality}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@ import { KBService } from "./../services/KBService";
|
|||
import { BotAdapter } from "botbuilder";
|
||||
import { Messages } from "../strings";
|
||||
import { LuisRecognizer } from "botbuilder-ai";
|
||||
import { GuaribasQuestion } from "../models";
|
||||
|
||||
const logger = require("../../../src/logger");
|
||||
|
||||
|
@ -58,6 +59,24 @@ export class AskDialog extends IGBDialog {
|
|||
serviceEndpoint: min.instance.nlpServerUrl
|
||||
});
|
||||
|
||||
min.dialogs.add("/answerEvent", [
|
||||
async (dc, args) => {
|
||||
|
||||
if (args && args.questionId) {
|
||||
|
||||
let question = await service.getQuestionById(min.instance.instanceId, args.questionId);
|
||||
let answer = await service.getAnswerById(min.instance.instanceId, question.answerId)
|
||||
|
||||
// Sends the answer to all outputs, including projector.
|
||||
|
||||
await service.sendAnswer(
|
||||
min.conversationalService,
|
||||
dc,
|
||||
answer
|
||||
);
|
||||
}
|
||||
}])
|
||||
|
||||
min.dialogs.add("/answer", [
|
||||
async (dc, args) => {
|
||||
// Initialize values.
|
||||
|
|
|
@ -84,7 +84,7 @@ export class MenuDialog extends IGBDialog {
|
|||
)
|
||||
await min.conversationalService.sendEvent(dc, "play", {
|
||||
playerType: "bullet",
|
||||
data: data.slice(0, 6)
|
||||
data: data.slice(0, 10)
|
||||
})
|
||||
}
|
||||
} else {
|
||||
|
@ -109,12 +109,13 @@ export class MenuDialog extends IGBDialog {
|
|||
var subject = item
|
||||
var card = CardFactory.heroCard(
|
||||
subject.title,
|
||||
subject.description,
|
||||
CardFactory.images([
|
||||
UrlJoin(
|
||||
"/kb",
|
||||
min.instance.kb,
|
||||
"subjects",
|
||||
subject.internalId + ".png" // TODO: or fallback to subject.png
|
||||
"subject.png"
|
||||
)
|
||||
]),
|
||||
CardFactory.actions([
|
||||
|
@ -123,7 +124,9 @@ export class MenuDialog extends IGBDialog {
|
|||
title: Messages[locale].menu_select,
|
||||
value: JSON.stringify({
|
||||
title: subject.title,
|
||||
description: subject.description,
|
||||
subjectId: subject.subjectId,
|
||||
internalId: subject.internalId,
|
||||
to: subject.to
|
||||
})
|
||||
}
|
||||
|
|
|
@ -54,7 +54,8 @@ import {
|
|||
DataType,
|
||||
IsUUID,
|
||||
PrimaryKey,
|
||||
AutoIncrement
|
||||
AutoIncrement,
|
||||
HasOne
|
||||
} from "sequelize-typescript"
|
||||
|
||||
import { GuaribasUser } from "../../security.gblib/models"
|
||||
|
@ -71,6 +72,7 @@ export class GuaribasSubject extends Model<GuaribasSubject> {
|
|||
|
||||
@Column title: string
|
||||
|
||||
@Column(DataType.STRING(512))
|
||||
@Column description: string
|
||||
|
||||
@Column from: string
|
||||
|
@ -201,6 +203,20 @@ export class GuaribasAnswer extends Model<GuaribasAnswer> {
|
|||
@HasMany(() => GuaribasQuestion)
|
||||
questions: GuaribasQuestion[]
|
||||
|
||||
@HasOne(() => GuaribasQuestion)
|
||||
prev: GuaribasQuestion
|
||||
|
||||
@HasOne(() => GuaribasQuestion)
|
||||
next: GuaribasQuestion
|
||||
|
||||
@ForeignKey(() => GuaribasQuestion)
|
||||
@Column
|
||||
nextId: number
|
||||
|
||||
@ForeignKey(() => GuaribasQuestion)
|
||||
@Column
|
||||
prevId: number
|
||||
|
||||
@ForeignKey(() => GuaribasInstance)
|
||||
@Column
|
||||
instanceId: number
|
||||
|
|
|
@ -63,23 +63,28 @@ export class KBService {
|
|||
this.sequelize = sequelize
|
||||
}
|
||||
|
||||
async getQuestionById(
|
||||
instanceId: number,
|
||||
questionId: number
|
||||
): Promise<GuaribasQuestion> {
|
||||
return GuaribasQuestion.findOne({
|
||||
where: {
|
||||
instanceId: instanceId,
|
||||
questionId: questionId
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async getAnswerById(
|
||||
instanceId: number,
|
||||
answerId: number
|
||||
): Promise<GuaribasAnswer> {
|
||||
return new Promise<GuaribasAnswer>(
|
||||
(resolve, reject) => {
|
||||
GuaribasAnswer.findAll({
|
||||
where: {
|
||||
instanceId: instanceId,
|
||||
answerId: answerId
|
||||
}
|
||||
}).then((item: GuaribasAnswer[]) => {
|
||||
resolve(item[0])
|
||||
}).error((reason) => {
|
||||
reject(reason)
|
||||
})
|
||||
})
|
||||
return GuaribasAnswer.findOne({
|
||||
where: {
|
||||
instanceId: instanceId,
|
||||
answerId: answerId
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async getAnswerByText(
|
||||
|
@ -291,7 +296,7 @@ export class KBService {
|
|||
static getSubjectItemsSeparatedBySpaces(subjects: GuaribasSubject[]) {
|
||||
let out = []
|
||||
subjects.forEach(subject => {
|
||||
out.push(subject.title)
|
||||
out.push(subject.internalId)
|
||||
})
|
||||
return out.join(" ")
|
||||
}
|
||||
|
@ -300,66 +305,37 @@ export class KBService {
|
|||
instanceId: number,
|
||||
parentId: number
|
||||
): Promise<GuaribasSubject[]> {
|
||||
return new Promise<GuaribasSubject[]>(
|
||||
(resolve, reject) => {
|
||||
var where = { parentSubjectId: parentId, instanceId: instanceId }
|
||||
GuaribasSubject.findAll({
|
||||
where: where
|
||||
})
|
||||
.then((values: GuaribasSubject[]) => {
|
||||
resolve(values)
|
||||
})
|
||||
.error(reason => {
|
||||
reject(reason)
|
||||
})
|
||||
})
|
||||
var where = { parentSubjectId: parentId, instanceId: instanceId }
|
||||
return GuaribasSubject.findAll({
|
||||
where: where
|
||||
})
|
||||
}
|
||||
|
||||
async getFaqBySubjectArray(from: string, subjects: any): Promise<GuaribasQuestion[]> {
|
||||
return new Promise<GuaribasQuestion[]>(
|
||||
(resolve, reject) => {
|
||||
let where = {
|
||||
from: from
|
||||
}
|
||||
|
||||
let where = {
|
||||
from: from
|
||||
}
|
||||
if (subjects) {
|
||||
if (subjects[0]) {
|
||||
where["subject1"] = subjects[0].internalId
|
||||
}
|
||||
|
||||
if (subjects) {
|
||||
if (subjects[0]) {
|
||||
where["subject1"] = subjects[0].title
|
||||
}
|
||||
if (subjects[1]) {
|
||||
where["subject2"] = subjects[1].internalId
|
||||
}
|
||||
|
||||
if (subjects[1]) {
|
||||
where["subject2"] = subjects[1].title
|
||||
}
|
||||
if (subjects[2]) {
|
||||
where["subject3"] = subjects[2].internalId
|
||||
}
|
||||
|
||||
if (subjects[2]) {
|
||||
where["subject3"] = subjects[2].title
|
||||
}
|
||||
|
||||
if (subjects[3]) {
|
||||
where["subject4"] = subjects[3].title
|
||||
}
|
||||
}
|
||||
GuaribasQuestion.findAll({
|
||||
where: where
|
||||
})
|
||||
.then((items: GuaribasQuestion[]) => {
|
||||
if (!items) items = []
|
||||
if (items.length == 0) {
|
||||
resolve([])
|
||||
} else {
|
||||
resolve(items)
|
||||
}
|
||||
})
|
||||
.catch(reason => {
|
||||
if (reason.message.indexOf("no such table: IGBInstance") != -1) {
|
||||
resolve([])
|
||||
} else {
|
||||
reject(reason)
|
||||
logger.info(`GuaribasServiceError: ${reason}`)
|
||||
}
|
||||
})
|
||||
})
|
||||
if (subjects[3]) {
|
||||
where["subject4"] = subjects[3].internalId
|
||||
}
|
||||
}
|
||||
return await GuaribasQuestion.findAll({
|
||||
where: where
|
||||
})
|
||||
}
|
||||
|
||||
async importKbTabularFile(
|
||||
|
@ -373,6 +349,9 @@ export class KBService {
|
|||
delimiter: "\t"
|
||||
}
|
||||
|
||||
let lastQuestion: GuaribasQuestion;
|
||||
let lastAnswer: GuaribasAnswer;
|
||||
|
||||
let data = await parse(file, opts)
|
||||
return asyncPromise.eachSeries(data, async line => {
|
||||
|
||||
|
@ -428,9 +407,11 @@ export class KBService {
|
|||
instanceId: instanceId,
|
||||
content: answer,
|
||||
format: format,
|
||||
packageId: packageId
|
||||
packageId: packageId,
|
||||
prevId: lastQuestion ? lastQuestion.questionId : 0,
|
||||
})
|
||||
await GuaribasQuestion.create({
|
||||
|
||||
let question1 = await GuaribasQuestion.create({
|
||||
from: from,
|
||||
to: to,
|
||||
subject1: subject1,
|
||||
|
@ -443,7 +424,13 @@ export class KBService {
|
|||
packageId: packageId
|
||||
})
|
||||
|
||||
return Promise.resolve(question)
|
||||
if (lastAnswer && lastQuestion) {
|
||||
await lastAnswer.updateAttributes({ nextId: lastQuestion.questionId })
|
||||
}
|
||||
lastAnswer = answer1
|
||||
lastQuestion = question1
|
||||
|
||||
return Promise.resolve(lastQuestion)
|
||||
|
||||
} else {
|
||||
|
||||
|
@ -465,7 +452,7 @@ export class KBService {
|
|||
} else if (answer.content.length > 140 &&
|
||||
dc.context._activity.channelId === "webchat") {
|
||||
const locale = dc.context.activity.locale;
|
||||
|
||||
|
||||
await dc.context.sendActivity(Messages[locale].will_answer_projector) // TODO: Handle rnd.
|
||||
var html = answer.content
|
||||
|
||||
|
@ -483,7 +470,13 @@ export class KBService {
|
|||
})
|
||||
html = marked(answer.content)
|
||||
}
|
||||
await conversationalService.sendEvent(dc, "play", { playerType: "markdown", data: html })
|
||||
await conversationalService.sendEvent(dc, "play",
|
||||
{
|
||||
playerType: "markdown", data: {
|
||||
content: html, answer: answer,
|
||||
prevId: answer.prevId, nextId: answer.nextId
|
||||
}
|
||||
})
|
||||
} else {
|
||||
await dc.context.sendActivity(answer.content)
|
||||
await conversationalService.sendEvent(dc, "stop", null)
|
||||
|
@ -560,10 +553,8 @@ export class KBService {
|
|||
else {
|
||||
return Promise.resolve(item)
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
return doIt(subjects.children, null)
|
||||
}
|
||||
|
||||
|
@ -603,11 +594,11 @@ export class KBService {
|
|||
)
|
||||
|
||||
let instance = await core.loadInstance(packageObject.botId)
|
||||
logger.info(`[GBDeployer] Beginning importing: ${localPath}`)
|
||||
logger.info(`[GBDeployer] Importing: ${localPath}`)
|
||||
let p = await deployer.deployPackageToStorage(
|
||||
instance.instanceId,
|
||||
packageName)
|
||||
await this.importKbPackage(localPath, p, instance)
|
||||
logger.info(`[GBDeployer] Finished importing ${localPath}`)
|
||||
logger.info(`[GBDeployer] Finished import of ${localPath}`)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue