fix(basic.gblib): COPY and CONVERT is now generating good JS.
This commit is contained in:
parent
8614ff4a8e
commit
3f13609d59
13 changed files with 262 additions and 63 deletions
7
package-lock.json
generated
7
package-lock.json
generated
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "botserver",
|
||||
"version": "2.0.79",
|
||||
"version": "2.0.91",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
@ -20344,6 +20344,11 @@
|
|||
"spdx-ranges": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"speakingurl": {
|
||||
"version": "14.0.1",
|
||||
"resolved": "https://registry.npmjs.org/speakingurl/-/speakingurl-14.0.1.tgz",
|
||||
"integrity": "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ=="
|
||||
},
|
||||
"split": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz",
|
||||
|
|
|
@ -100,6 +100,7 @@
|
|||
"sequelize": "5.21.5",
|
||||
"sequelize-typescript": "1.1.0",
|
||||
"simple-git": "2.23.0",
|
||||
"speakingurl": "^14.0.1",
|
||||
"sppull": "2.6.7",
|
||||
"strict-password-generator": "1.1.2",
|
||||
"swagger-client": "2.1.18",
|
||||
|
|
|
@ -49,6 +49,7 @@ import { GuaribasAdmin } from '../models/AdminModel';
|
|||
const Path = require('path');
|
||||
const msRestAzure = require('ms-rest-azure');
|
||||
const PasswordGenerator = require('strict-password-generator').default;
|
||||
const crypto = require("crypto");
|
||||
|
||||
/**
|
||||
* Services for server administration.
|
||||
|
@ -145,6 +146,21 @@ export class GBAdminService implements IGBAdminService {
|
|||
return passwordGenerator.generatePassword(options);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see https://stackoverflow.com/a/52171480
|
||||
*/
|
||||
public static getHash(str, seed = 0) {
|
||||
let h1 = 0xdeadbeef ^ seed, h2 = 0x41c6ce57 ^ seed;
|
||||
for (let i = 0, ch; i < str.length; i++) {
|
||||
ch = str.charCodeAt(i);
|
||||
h1 = Math.imul(h1 ^ ch, 2654435761);
|
||||
h2 = Math.imul(h2 ^ ch, 1597334677);
|
||||
}
|
||||
h1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507) ^ Math.imul(h2 ^ (h2 >>> 13), 3266489909);
|
||||
h2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507) ^ Math.imul(h1 ^ (h1 >>> 13), 3266489909);
|
||||
return 4294967296 * (2097151 & h2) + (h1 >>> 0);
|
||||
}
|
||||
|
||||
public static async undeployPackageCommand(text: any, min: GBMinInstance) {
|
||||
const packageName = text.split(' ')[1];
|
||||
const importer = new GBImporter(min.core);
|
||||
|
@ -176,7 +192,7 @@ export class GBAdminService implements IGBAdminService {
|
|||
// .gbot packages are handled using storage API, so no download
|
||||
// of local resources is required.
|
||||
|
||||
|
||||
|
||||
if (!localFolder.endsWith('.gbot')) {
|
||||
GBLog.warn(`${GBConfigService.get('CLOUD_USERNAME')} must be authorized on SharePoint related site to download to: ${localFolder}`);
|
||||
await s.downloadFolder(
|
||||
|
@ -261,7 +277,7 @@ export class GBAdminService implements IGBAdminService {
|
|||
const refreshToken = await this.getValue(instanceId, 'refreshToken');
|
||||
const resource = 'https://graph.microsoft.com';
|
||||
const authenticationContext = new AuthenticationContext(authorizationUrl);
|
||||
|
||||
|
||||
authenticationContext.acquireTokenWithRefreshToken(
|
||||
refreshToken,
|
||||
instance.marketplaceId,
|
||||
|
|
|
@ -289,8 +289,12 @@ export class GBVMService extends GBService {
|
|||
return `sendFile (step, ${$3})\n`;
|
||||
});
|
||||
|
||||
code = code.replace(/(COPY)(\s*)(.*)/gi, ($0, $1, $2, $3) => {
|
||||
return `sys().copyFile (step, ${$3})\n`;
|
||||
code = code.replace(/(copy)(\s*)(.*)/gi, ($0, $1, $2, $3) => {
|
||||
return `sys().copyFile(step, ${$3})\n`;
|
||||
});
|
||||
|
||||
code = code.replace(/(convert)(\s*)(.*)/gi, ($0, $1, $2, $3) => {
|
||||
return `sys().convert(step, ${$3})\n`;
|
||||
});
|
||||
|
||||
code = code.replace(/(save)(\s)(.*)/gi, ($0, $1, $2, $3) => {
|
||||
|
@ -433,9 +437,6 @@ export class GBVMService extends GBService {
|
|||
code = code.replace(/("[^"]*"|'[^']*')|\bsendFileTo\b/gi, ($0, $1) => {
|
||||
return $1 === undefined ? 'this.sendFileTo' : $1;
|
||||
});
|
||||
code = code.replace(/("[^"]*"|'[^']*')|\bcopyFile\b/gi, ($0, $1) => {
|
||||
return $1 === undefined ? 'this.copyFile' : $1;
|
||||
});
|
||||
code = code.replace(/("[^"]*"|'[^']*')|\bsendFile\b/gi, ($0, $1) => {
|
||||
return $1 === undefined ? 'this.sendFile' : $1;
|
||||
});
|
||||
|
@ -448,7 +449,7 @@ export class GBVMService extends GBService {
|
|||
code = code.replace(/("[^"]*"|'[^']*')|\bmenu\b/gi, ($0, $1) => {
|
||||
return $1 === undefined ? 'this.menu' : $1;
|
||||
});
|
||||
|
||||
|
||||
// await insertion.
|
||||
|
||||
code = code.replace(/this\./gm, 'await this.');
|
||||
|
|
|
@ -186,7 +186,7 @@ export class GBDeployer implements IGBDeployer {
|
|||
const instances = await core.loadInstances();
|
||||
await CollectionUtil.asyncForEach(instances, async instance => {
|
||||
this.mountGBKBAssets(`${instance.botId}.gbkb`,
|
||||
instance.botId, `${instance.botId}.gbkb`);
|
||||
instance.botId, `${instance.botId}.gbkb`);
|
||||
});
|
||||
|
||||
GBLog.info(`Package deployment done.`);
|
||||
|
@ -320,7 +320,7 @@ export class GBDeployer implements IGBDeployer {
|
|||
public async publishNLP(instance: IGBInstance): Promise<void> {
|
||||
const service = new AzureDeployerService(this);
|
||||
const res = await service.publishNLP(instance.cloudLocation, instance.nlpAppId,
|
||||
instance.nlpAuthoringKey);
|
||||
instance.nlpAuthoringKey);
|
||||
if (res.status !== 200 && res.status !== 201) { throw res.bodyAsText; }
|
||||
}
|
||||
|
||||
|
@ -371,29 +371,29 @@ export class GBDeployer implements IGBDeployer {
|
|||
const libraryId = process.env.STORAGE_LIBRARY;
|
||||
|
||||
GBLog.info(`Connecting to Config.xslx (siteId: ${siteId}, libraryId: ${libraryId})...`);
|
||||
|
||||
|
||||
// Connects to MSFT storage.
|
||||
|
||||
|
||||
const token = await min.adminService.acquireElevatedToken(min.instance.instanceId);
|
||||
const client = MicrosoftGraph.Client.init({
|
||||
authProvider: done => {
|
||||
done(null, token);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Retrieves all files in .bot folder.
|
||||
|
||||
|
||||
const botId = min.instance.botId;
|
||||
const path = `/${botId}.gbai/${botId}.gbot`;
|
||||
let url = `https://graph.microsoft.com/v1.0/sites/${siteId}/lists/${libraryId}/drive/root:${path}:/children`;
|
||||
|
||||
GBLog.info(`Loading .gbot from Excel: ${url}`);
|
||||
const res = await client
|
||||
.api(url)
|
||||
.get();
|
||||
|
||||
.api(url)
|
||||
.get();
|
||||
|
||||
// Finds Config.xlsx.
|
||||
|
||||
|
||||
const document = res.value.filter(m => {
|
||||
return m.name === 'Config.xlsx';
|
||||
});
|
||||
|
@ -496,14 +496,14 @@ export class GBDeployer implements IGBDeployer {
|
|||
if (handled) {
|
||||
return pck;
|
||||
}
|
||||
|
||||
|
||||
// Deploy platform packages here accordingly to their extension.
|
||||
|
||||
|
||||
switch (packageType) {
|
||||
case '.gbot':
|
||||
|
||||
|
||||
// Extracts configuration information from .gbot files.
|
||||
|
||||
|
||||
if (process.env.ENABLE_PARAMS_ONLINE === 'false') {
|
||||
if (Fs.existsSync(localPath)) {
|
||||
GBLog.info(`Loading .gbot from ${localPath}.`);
|
||||
|
@ -512,9 +512,9 @@ export class GBDeployer implements IGBDeployer {
|
|||
} else {
|
||||
min.instance.params = await this.loadParamsFromTabular(min);
|
||||
}
|
||||
|
||||
|
||||
// Updates instance object.
|
||||
|
||||
|
||||
await this.core.saveInstance(min.instance);
|
||||
|
||||
break;
|
||||
|
@ -561,6 +561,7 @@ export class GBDeployer implements IGBDeployer {
|
|||
break;
|
||||
|
||||
default:
|
||||
|
||||
const err = GBError.create(`Unhandled package type: ${packageType}.`);
|
||||
Promise.reject(err);
|
||||
break;
|
||||
|
@ -581,6 +582,7 @@ export class GBDeployer implements IGBDeployer {
|
|||
// Removes objects from storage, cloud resources and local files if any.
|
||||
|
||||
switch (packageType) {
|
||||
|
||||
case '.gbot':
|
||||
const packageObject = JSON.parse(Fs.readFileSync(urlJoin(localPath, 'package.json'), 'utf8'));
|
||||
await this.undeployBot(packageObject.botId, packageName);
|
||||
|
@ -596,17 +598,17 @@ export class GBDeployer implements IGBDeployer {
|
|||
break;
|
||||
|
||||
case '.gbtheme':
|
||||
rimraf.sync(localPath);
|
||||
break;
|
||||
|
||||
case '.gbdialog':
|
||||
rimraf.sync(localPath);
|
||||
break;
|
||||
|
||||
case '.gblib':
|
||||
break;
|
||||
|
||||
case '.gbapp':
|
||||
break;
|
||||
|
||||
default:
|
||||
const err = GBError.create(`Unhandled package type: ${packageType}.`);
|
||||
Promise.reject(err);
|
||||
|
@ -647,6 +649,7 @@ export class GBDeployer implements IGBDeployer {
|
|||
}
|
||||
|
||||
// Removes the index.
|
||||
|
||||
try {
|
||||
await search.deleteIndex();
|
||||
} catch (err) {
|
||||
|
@ -659,6 +662,7 @@ export class GBDeployer implements IGBDeployer {
|
|||
}
|
||||
|
||||
// Creates the data source and index on the cloud.
|
||||
|
||||
try {
|
||||
await search.createDataSource(dsName, dsName, 'GuaribasQuestion', 'azuresql', connectionString);
|
||||
} catch (err) {
|
||||
|
@ -694,7 +698,7 @@ export class GBDeployer implements IGBDeployer {
|
|||
|
||||
if (!Fs.existsSync(`${root}/build`) && process.env.DISABLE_WEB !== 'true') {
|
||||
|
||||
// Write a .env required to fix some bungs in create-react-app facility.
|
||||
// Write a .env required to fix some bungs in create-react-app tool.
|
||||
|
||||
Fs.writeFileSync(`${root}/.env`, 'SKIP_PREFLIGHT_CHECK=true');
|
||||
|
||||
|
@ -702,15 +706,18 @@ export class GBDeployer implements IGBDeployer {
|
|||
|
||||
GBLog.info(`Installing modules default.gbui (It may take a few minutes)...`);
|
||||
child_process.execSync(`${npm} install`, { cwd: root });
|
||||
|
||||
GBLog.info(`Transpiling default.gbui...`);
|
||||
child_process.execSync(`${npm} run build`, { cwd: root });
|
||||
}
|
||||
|
||||
// Clean up node_modules folder as it is only needed during compile time.
|
||||
|
||||
GBLog.info(`Cleaning default.gbui node_modules...`);
|
||||
const nodeModules = urlJoin(root, 'node_modules');
|
||||
rimraf.sync(nodeModules);
|
||||
if (Fs.existsSync(nodeModules)) {
|
||||
rimraf.sync(nodeModules);
|
||||
GBLog.info(`Cleaning default.gbui node_modules...`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -729,13 +736,13 @@ export class GBDeployer implements IGBDeployer {
|
|||
|
||||
const gbaiName = `${botId}.gbai`;
|
||||
GBServer.globals.server.use(`/kb/${gbaiName}/${packageName}/assets`,
|
||||
express.static(urlJoin('work', gbaiName, filename, 'assets')));
|
||||
express.static(urlJoin('work', gbaiName, filename, 'assets')));
|
||||
GBServer.globals.server.use(`/kb/${gbaiName}/${packageName}/images`,
|
||||
express.static(urlJoin('work', gbaiName, filename, 'images')));
|
||||
express.static(urlJoin('work', gbaiName, filename, 'images')));
|
||||
GBServer.globals.server.use(`/kb/${gbaiName}/${packageName}/audios`,
|
||||
express.static(urlJoin('work', gbaiName, filename, 'audios')));
|
||||
express.static(urlJoin('work', gbaiName, filename, 'audios')));
|
||||
GBServer.globals.server.use(`/kb/${gbaiName}/${packageName}/videos`,
|
||||
express.static(urlJoin('work', gbaiName, filename, 'videos')));
|
||||
express.static(urlJoin('work', gbaiName, filename, 'videos')));
|
||||
|
||||
GBLog.info(`KB (.gbkb) assets accessible at: /kb/${botId}.gbai/${packageName}.`);
|
||||
}
|
||||
|
|
|
@ -131,6 +131,7 @@ export class GBMinService {
|
|||
public async buildMin(instances: IGBInstance[]) {
|
||||
|
||||
// Servers default UI on root address '/' if web enabled.
|
||||
|
||||
if (process.env.DISABLE_WEB !== 'true') {
|
||||
const url = GBServer.globals.wwwroot
|
||||
? GBServer.globals.wwwroot
|
||||
|
@ -139,6 +140,8 @@ export class GBMinService {
|
|||
GBServer.globals.server.use('/', express.static(url));
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Servers the bot information object via HTTP so clients can get
|
||||
// instance information stored on server.
|
||||
|
||||
|
@ -216,12 +219,13 @@ export class GBMinService {
|
|||
|
||||
await this.invokeLoadBot(GBServer.globals.appPackages, GBServer.globals.sysPackages, min);
|
||||
|
||||
// Serves individual URL for each bot conversational interface...
|
||||
// Serves individual URL for each bot conversational interface.
|
||||
|
||||
const url = `/api/messages/${instance.botId}`;
|
||||
GBServer.globals.server.post(url, async (req, res) => {
|
||||
const receiver = async (req, res) => {
|
||||
await this.receiver(adapter, req, res, conversationState, min, instance, GBServer.globals.appPackages);
|
||||
});
|
||||
};
|
||||
const url = `/api/messages/${instance.botId}`;
|
||||
GBServer.globals.server.post(url, receiver);
|
||||
GBLog.info(`GeneralBots(${instance.engineName}) listening on: ${url}.`);
|
||||
|
||||
// Serves individual URL for each bot user interface.
|
||||
|
@ -237,7 +241,14 @@ export class GBMinService {
|
|||
uiUrlAlt,
|
||||
express.static(urlJoin(GBDeployer.deployFolder, GBMinService.uiPackage, 'build'))
|
||||
);
|
||||
|
||||
const domain = min.core.getParam(min.instance, 'Domain', null);
|
||||
if (domain) {
|
||||
GBServer.globals.server.use(
|
||||
domain,
|
||||
express.static(urlJoin(GBDeployer.deployFolder, GBMinService.uiPackage, 'build'))
|
||||
);
|
||||
GBLog.info(`Bot UI ${GBMinService.uiPackage} accessible at custom domain: ${domain}.`);
|
||||
}
|
||||
GBLog.info(`Bot UI ${GBMinService.uiPackage} accessible at: ${uiUrl} and ${uiUrlAlt}.`);
|
||||
}
|
||||
|
||||
|
@ -512,7 +523,12 @@ export class GBMinService {
|
|||
speechToken: speechToken,
|
||||
conversationId: webchatTokenContainer.conversationId,
|
||||
authenticatorTenant: instance.authenticatorTenant,
|
||||
authenticatorClientId: instance.marketplaceId
|
||||
authenticatorClientId: instance.marketplaceId,
|
||||
paramLogoImageUrl: this.core.getParam(instance, 'Logo Image Url', null),
|
||||
paramLogoImageAlt: this.core.getParam(instance, 'Logo Image Alt', null),
|
||||
paramLogoImageWidth: this.core.getParam(instance, 'Logo Image Width', null),
|
||||
paramLogoImageHeight: this.core.getParam(instance, 'Logo Image Height', null),
|
||||
paramLogoImageType: this.core.getParam(instance, 'Logo Image Type', null)
|
||||
})
|
||||
);
|
||||
} else {
|
||||
|
@ -603,6 +619,7 @@ export class GBMinService {
|
|||
if (GBServer.globals.minBoot === undefined) {
|
||||
GBServer.globals.minBoot = min;
|
||||
}
|
||||
|
||||
// TODO: min.appPackages = core.getPackagesByInstanceId(min.instance.instanceId);
|
||||
|
||||
// Creates a hub of services available in .gbapps.
|
||||
|
@ -735,7 +752,7 @@ export class GBMinService {
|
|||
user.welcomed = false;
|
||||
firstTime = true;
|
||||
|
||||
// Sends loadInstance event to .gbui clients.
|
||||
// Sends loadInstance event to .gbui clients and loads FAQ.
|
||||
|
||||
await min.conversationalService.sendEvent(min, step, 'loadInstance', {
|
||||
instanceId: instance.instanceId,
|
||||
|
@ -743,6 +760,12 @@ export class GBMinService {
|
|||
theme: instance.theme ? instance.theme : 'default.gbtheme',
|
||||
secret: instance.webchatKey
|
||||
});
|
||||
const service = new KBService(min.core.sequelize);
|
||||
const data = await service.getFaqBySubjectArray('faq', undefined);
|
||||
await min.conversationalService.sendEvent(min, step, 'play', {
|
||||
playerType: 'bullet',
|
||||
data: data.slice(0, 10)
|
||||
});
|
||||
|
||||
// This same event is dispatched either to all participants
|
||||
// including the bot, that is filtered bellow.
|
||||
|
|
36
packages/default.gbui/package-lock.json
generated
36
packages/default.gbui/package-lock.json
generated
|
@ -1199,6 +1199,11 @@
|
|||
"@types/yargs": "^13.0.0"
|
||||
}
|
||||
},
|
||||
"@midudev/react-static-content": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@midudev/react-static-content/-/react-static-content-1.0.4.tgz",
|
||||
"integrity": "sha512-P2+rdqhysYNon5/noOoUiFJghVxbl64qGgxsKwe10mjrkQvgIy4vCcOLN5Nw00er/cBSuWY/hVHkuSeQ6sI5VA=="
|
||||
},
|
||||
"@mrmlnc/readdir-enhanced": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz",
|
||||
|
@ -11919,6 +11924,37 @@
|
|||
"shallowequal": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"react-super-seo": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/react-super-seo/-/react-super-seo-1.0.5.tgz",
|
||||
"integrity": "sha512-OtenkmcfjA97kaem/HxL0oaRO3hYhfalaoNt2I1nAVMzGh3I/xDWwy+J4ynA6LlPc+SqBY5BHcrRzjWT75hr1A==",
|
||||
"requires": {
|
||||
"react-helmet": "^6.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"react-fast-compare": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz",
|
||||
"integrity": "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA=="
|
||||
},
|
||||
"react-helmet": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/react-helmet/-/react-helmet-6.1.0.tgz",
|
||||
"integrity": "sha512-4uMzEY9nlDlgxr61NL3XbKRy1hEkXmKNXhjbAIOVw5vcFrsdYbH2FEwcNyWvWinl103nXgzYNlns9ca+8kFiWw==",
|
||||
"requires": {
|
||||
"object-assign": "^4.1.1",
|
||||
"prop-types": "^15.7.2",
|
||||
"react-fast-compare": "^3.1.1",
|
||||
"react-side-effect": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"react-side-effect": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/react-side-effect/-/react-side-effect-2.1.1.tgz",
|
||||
"integrity": "sha512-2FoTQzRNTncBVtnzxFOk2mCpcfxQpenBMbk5kSVBg5UcPqV9fRbgY2zhb7GTWWOlpFmAxhClBDlIq8Rsubz1yQ=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"react-transition-group": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.3.0.tgz",
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
"license": "AGPL-3.0",
|
||||
"homepage": ".",
|
||||
"dependencies": {
|
||||
"@midudev/react-static-content": "^1.0.4",
|
||||
"ajv": "^6.10.2",
|
||||
"botframework-directlinejs": "0.11.6",
|
||||
"botframework-webchat": "^4.7.1",
|
||||
|
@ -20,6 +21,7 @@
|
|||
"react-player": "^1.14.2",
|
||||
"react-powerbi": "0.5.2",
|
||||
"react-scripts": "^3.3.0",
|
||||
"react-super-seo": "^1.0.5",
|
||||
"react-transition-group": "^4.3.0",
|
||||
"rxjs": "^6.5.4",
|
||||
"url-join": "4.0.1"
|
||||
|
|
|
@ -37,12 +37,13 @@ import GBVideoPlayer from './players/GBVideoPlayer.js';
|
|||
import GBLoginPlayer from './players/GBLoginPlayer.js';
|
||||
import GBBulletPlayer from './players/GBBulletPlayer.js';
|
||||
import SidebarMenu from './components/SidebarMenu.js';
|
||||
import SEO from './components/SEO.js';
|
||||
import GBCss from './components/GBCss.js';
|
||||
import { DirectLine } from 'botframework-directlinejs';
|
||||
import { ConnectionStatus } from 'botframework-directlinejs';
|
||||
import ReactWebChat from 'botframework-webchat';
|
||||
import { UserAgentApplication } from 'msal';
|
||||
|
||||
import StaticContent from '@midudev/react-static-content'
|
||||
|
||||
class GBUIApp extends React.Component {
|
||||
constructor() {
|
||||
|
@ -138,7 +139,7 @@ class GBUIApp extends React.Component {
|
|||
}
|
||||
|
||||
authenticate() {
|
||||
|
||||
|
||||
if (this.state.instanceClient.authenticatorClientId === null) {
|
||||
return;
|
||||
}
|
||||
|
@ -343,14 +344,17 @@ class GBUIApp extends React.Component {
|
|||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
{gbCss}
|
||||
{sideBar}
|
||||
<div className="player">{playerComponent}</div>
|
||||
<div className="webchat">
|
||||
{chat}
|
||||
<StaticContent>
|
||||
<SEO></SEO>
|
||||
<div>
|
||||
{gbCss}
|
||||
{sideBar}
|
||||
<div className="player">{playerComponent}</div>
|
||||
<div className="webchat">
|
||||
{chat}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</StaticContent>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
58
packages/default.gbui/src/components/SEO.js
Normal file
58
packages/default.gbui/src/components/SEO.js
Normal file
|
@ -0,0 +1,58 @@
|
|||
/*****************************************************************************\
|
||||
| ( )_ _ |
|
||||
| _ _ _ __ _ _ __ ___ ___ _ _ | ,_)(_) ___ ___ _ |
|
||||
| ( '_`\ ( '__)/'_` ) /'_ `\/' _ ` _ `\ /'_` )| | | |/',__)/' v `\ /'_`\ |
|
||||
| | (_) )| | ( (_| |( (_) || ( ) ( ) |( (_| || |_ | |\__, \| (˅) |( (_) ) |
|
||||
| | ,__/'(_) `\__,_)`\__ |(_) (_) (_)`\__,_)`\__)(_)(____/(_) (_)`\___/' |
|
||||
| | | ( )_) | |
|
||||
| (_) \___/' |
|
||||
| |
|
||||
| General Bots Copyright (c) Pragmatismo.io. All rights reserved. |
|
||||
| Licensed under the AGPL-3.0. |
|
||||
| |
|
||||
| According to our dual licensing model, this program can be used either |
|
||||
| under the terms of the GNU Affero General Public License, version 3, |
|
||||
| or under a proprietary license. |
|
||||
| |
|
||||
| The texts of the GNU Affero General Public License with an additional |
|
||||
| permission and of our proprietary license can be found at and |
|
||||
| in the LICENSE file you have received along with this program. |
|
||||
| |
|
||||
| This program is distributed in the hope that it will be useful, |
|
||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||
| GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| "General Bots" is a registered trademark of Pragmatismo.io. |
|
||||
| The licensing of the program under the AGPLv3 does not imply a |
|
||||
| trademark license. Therefore any rights, title and interest in |
|
||||
| our trademarks remain entirely with us. |
|
||||
| |
|
||||
\*****************************************************************************/
|
||||
|
||||
import React from "react"
|
||||
import { SuperSEO } from 'react-super-seo';
|
||||
|
||||
const footer = () => (
|
||||
<SuperSEO
|
||||
title={this.props.instance.title}
|
||||
description={this.props.instance.description}
|
||||
lang="en"
|
||||
openGraph={{
|
||||
ogImage: {
|
||||
ogImage: this.props.instance.paramLogoImageUrl,
|
||||
ogImageAlt: this.props.instance.paramLogoImageAlt,
|
||||
ogImageWidth: this.props.instance.paramLogoImageWidth,
|
||||
ogImageHeight: this.props.instance.paramLogoImageHeight,
|
||||
ogImageType: this.props.instance.paramLogoImageType,
|
||||
},
|
||||
}}
|
||||
twitter={{
|
||||
twitterSummaryCard: {
|
||||
summaryCardImage: this.props.instance.paramLogoImageUrl,
|
||||
summaryCardImageAlt: this.props.instance.paramLogoImageAlt,
|
||||
summaryCardSiteUsername: this.props.instance.paramTwitterUsername,
|
||||
},
|
||||
}}
|
||||
/>);
|
||||
export default footer
|
|
@ -50,11 +50,10 @@ class SideBarMenu extends React.Component {
|
|||
return (
|
||||
<div>
|
||||
<div className="tittleSideBarMenu">
|
||||
<img
|
||||
className="pragmatismoLogo"
|
||||
src={"/themes/" + this.props.instance.theme + "/images/logo.png"}
|
||||
alt="General Bots Logo"
|
||||
/>
|
||||
<img
|
||||
className="pragmatismoLogo"
|
||||
src={"/themes/" + this.props.instance.theme + "/images/logo.png"}
|
||||
alt="General Bots Logo" />
|
||||
|
||||
</div>
|
||||
<div className="SidebarMenu">
|
||||
|
@ -72,16 +71,14 @@ class SideBarMenu extends React.Component {
|
|||
<div className="iconMenu">
|
||||
<span
|
||||
className="iconText"
|
||||
onClick={() => this.send("showSubjects")}
|
||||
>
|
||||
onClick={() => this.send("showSubjects")}>
|
||||
Subjects
|
||||
</span>
|
||||
</div>
|
||||
<div className="iconMenu">
|
||||
<span
|
||||
className="iconText"
|
||||
onClick={() => this.send("giveFeedback")}
|
||||
>
|
||||
onClick={() => this.send("giveFeedback")}>
|
||||
Suggestions
|
||||
</span>
|
||||
</div>
|
||||
|
|
|
@ -44,6 +44,7 @@ const walkPromise = require('walk-promise');
|
|||
// tslint:disable-next-line:newline-per-chained-call
|
||||
const { SearchService } = require('azure-search-client');
|
||||
const Excel = require('exceljs');
|
||||
const getSlug = require('speakingurl');
|
||||
import {
|
||||
GBDialogStep,
|
||||
GBLog,
|
||||
|
@ -53,15 +54,14 @@ import {
|
|||
IGBInstance,
|
||||
IGBKBService
|
||||
} from 'botlib';
|
||||
import { GBAdminService } from '../../admin.gbapp/services/GBAdminService';
|
||||
import { CollectionUtil } from 'pragmatismo-io-framework';
|
||||
import { Op } from 'sequelize';
|
||||
import { Sequelize } from 'sequelize-typescript';
|
||||
import { GBServer } from '../../../src/app';
|
||||
import { AzureDeployerService } from '../../azuredeployer.gbapp/services/AzureDeployerService';
|
||||
import { GuaribasPackage } from '../../core.gbapp/models/GBModel';
|
||||
import { GBDeployer } from '../../core.gbapp/services/GBDeployer';
|
||||
import { CSService } from '../../customer-satisfaction.gbapp/services/CSService';
|
||||
import { SecService } from '../../security.gbapp/services/SecService';
|
||||
import { GuaribasAnswer, GuaribasQuestion, GuaribasSubject } from '../models';
|
||||
import { Messages } from '../strings';
|
||||
import { GBConfigService } from './../../core.gbapp/services/GBConfigService';
|
||||
|
@ -137,6 +137,54 @@ export class KBService implements IGBKBService {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a question object given a SEO friendly URL.
|
||||
*/
|
||||
public async getQuestionIdFromURL(core: IGBCoreService, url: string) {
|
||||
|
||||
// Extracts questionId from URL.
|
||||
|
||||
const id = url.substr(url.lastIndexOf('-') + 1);
|
||||
|
||||
// Extracts botId from URL.
|
||||
|
||||
let path = /(http[s]?:\/\/)?([^\/\s]+\/)(.*)/gi;
|
||||
const botId = url.replace(path, ($0, $1, $2, $3) => {
|
||||
return $3.substr($3.indexOf('/'));
|
||||
});
|
||||
|
||||
// Finds the associated question.
|
||||
|
||||
const instance = await core.loadInstanceByBotId(botId);
|
||||
const question = await GuaribasQuestion.findAll({
|
||||
where: {
|
||||
instanceId: instance.instanceId,
|
||||
questionId: id
|
||||
}
|
||||
});
|
||||
|
||||
return question;
|
||||
}
|
||||
|
||||
public async getQuestionsSEO(instanceId: number) {
|
||||
|
||||
const questions = await GuaribasQuestion.findAll({
|
||||
where: {
|
||||
instanceId: instanceId
|
||||
}
|
||||
});
|
||||
|
||||
let output = [];
|
||||
for (let i = 0; i < questions.length; i++) {
|
||||
const answer = questions[i];
|
||||
const text = getSlug(answer.content);
|
||||
let url = `${text}-${i}`;
|
||||
output.push(url);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
public async getAnswerByText(instanceId: number, text: string): Promise<any> {
|
||||
text = text.trim();
|
||||
const service = new CSService();
|
||||
|
@ -519,6 +567,7 @@ export class KBService implements IGBKBService {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
public async importKbTabularDirectory(localPath: string, instance: IGBInstance, packageId: number): Promise<any> {
|
||||
const files = await walkPromise(localPath);
|
||||
|
||||
|
|
|
@ -62,8 +62,8 @@ export class RootData {
|
|||
public appPackages: any[]; // Loaded .gbapp package list
|
||||
public minService: GBMinService; // Minimalist service core
|
||||
public bootInstance: IGBInstance; // General Bot Interface Instance
|
||||
public minInstances: any[]; //
|
||||
public minBoot: GBMinInstance;
|
||||
public minInstances: any[]; // List of bot instances.
|
||||
public minBoot: GBMinInstance; // Reference to boot bot.
|
||||
public wwwroot: string; // .gbui or a static webapp.
|
||||
public entryPointDialog: string; // To replace default welcome dialog.
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue