Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Epic ai rebased #7975

Open
wants to merge 59 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
7a3fd10
Create an Assistant MVP #7121
edloidas Jan 5, 2024
3504c53
Create an Assistant MVP #7121
ashklianko Jan 12, 2024
1365a0c
Create an Assistant MVP #7121
ashklianko Jan 18, 2024
5dc777f
Create an Assistant MVP #7121
ashklianko Jan 25, 2024
9aeb8be
Create an Assistant MVP #7121
ashklianko Jan 29, 2024
741187e
Create an Assistant MVP #7121
ashklianko Jan 30, 2024
e5a08ed
Create an Assistant MVP #7121
ashklianko Jan 30, 2024
7c64e99
fix 2 failed ui-tests
Jan 31, 2024
8a85d2b
AI Assistant: define event structure to communicate with Saga #7336
ashklianko Feb 8, 2024
314e263
Make content form inputs (textarea and htmlarea for now) and text com…
ashklianko Feb 12, 2024
da82c00
Add Assistant icon to the Content Wizard toolbar #7334
edloidas Feb 13, 2024
c863b80
Add Assistant icon to the Content Wizard toolbar #7334
ashklianko Feb 14, 2024
e2eea4b
Add Assistant icon to the Content Wizard toolbar #7334
ashklianko Feb 14, 2024
4fbcb4f
AI Assistant: send content data and schema to the assistant #7364
ashklianko Feb 15, 2024
2a0ecf2
AI Assistant: send content data and schema to the assistant #7364
ashklianko Feb 16, 2024
8d83217
AI Assistant: handle event with resulting data #7369
ashklianko Feb 20, 2024
d0f5ff4
AI Assistant: send config to the app #7395
ashklianko Mar 4, 2024
82974dc
Split AiAssistant config #7398
edloidas Mar 4, 2024
e2df520
Required for https://github.com/enonic/app-saga/issues/131
ashklianko Mar 12, 2024
30b72f1
Remove previous version of assistant from code #7452
ashklianko Mar 20, 2024
7807820
Enhance HtmlArea toolbar AI button #7453
ashklianko Mar 21, 2024
c1f3414
HtmlArea: focusing editor should insert mention into open Assistant d…
ashklianko Mar 21, 2024
651d312
Enhance HtmlArea toolbar AI button #7453
ashklianko Mar 22, 2024
ff2814f
Support custom promp #7596
ashklianko May 27, 2024
601545c
Add support for display name update from AI Assistant #7594
edloidas May 23, 2024
ba80b02
AI Assistant: pass updated Display Name to the assistant #7619
ashklianko May 29, 2024
3016a93
Make CS use Saga's REST service directly #7623
edloidas Jun 3, 2024
76cd01a
Prevent AI code from being injected, if the application is stopped #7625
edloidas Jun 3, 2024
921454b
Remove tooltip if target element was replaced #7638
edloidas Jun 4, 2024
c03c32d
Make assistant status polling limit configurable #7640
ashklianko Jun 4, 2024
434f1f1
Applying single field may lead to erasing data in other fields #7644
ashklianko Jun 5, 2024
008b85a
Making HtmlArea discoverable for updating data-path attr #7686
ashklianko Jun 24, 2024
fc87a06
Add Saga icons to text-based form items #7686
ashklianko Jun 25, 2024
ffefe75
Move Saga icon to collaboration block #7684
ashklianko Jun 27, 2024
f120656
Show AI icon only for inputs in content form #7702
ashklianko Jul 1, 2024
211b8c2
Let form decide if it's inputs to be AI interactable #3623
ashklianko Jul 1, 2024
f65b166
lint fix
ashklianko Jul 1, 2024
4dca837
Show AI icon only for inputs in content form #7702
edloidas Jul 1, 2024
2af6639
Suggest content localisation #7669
edloidas Jun 27, 2024
c1891a2
Sync CS and Saga apps #7706
ashklianko Jul 1, 2024
acab13f
Suggest content localisation #7669
edloidas Jul 1, 2024
098ecfa
ui-tests issue #7709
Jul 2, 2024
3e0bdb5
Request translations from AI Assistant #7671
edloidas Jul 1, 2024
c280e7e
Animate text input that is being translated #7670
ashklianko Jul 3, 2024
6a80b52
Animate text input that is being translated #7670
ashklianko Jul 3, 2024
192f555
Add new Saga REST endpoints #7713
edloidas Jul 3, 2024
d029f30
Add new Saga REST endpoints #7713
ashklianko Jul 4, 2024
a15d1a5
Add new Saga REST endpoints #7713
ashklianko Jul 4, 2024
bbb1539
Add new Saga REST endpoints #7713
ashklianko Jul 4, 2024
73025be
HtmlArea in an item-set is not being updated #7716
ashklianko Jul 5, 2024
0e396ce
AI translation: locked state look #7718
ashklianko Jul 5, 2024
c2f3d34
Assistant dialog localization #7739
ashklianko Jul 26, 2024
55ba69c
Rename translator service #7743
edloidas Jul 30, 2024
ccaf0fb
Update AI part to use new apps instead of Saga #7857
edloidas Sep 17, 2024
84ff55d
Update AI part to use new apps instead of Saga #7857
edloidas Sep 17, 2024
7d45eed
Update custom instructions handling #7884
edloidas Sep 20, 2024
dbf4c99
Rename isEditableByAi method
edloidas Sep 23, 2024
c9705ea
Fix instructions not applied #7967
edloidas Oct 16, 2024
eaa1c1e
epic-ai-rebased
ashklianko Oct 21, 2024
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
1 change: 1 addition & 0 deletions modules/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ dependencies {
include "com.enonic.xp:lib-schema:${xpVersion}"
include "com.enonic.lib:lib-admin-ui:${libAdminUiVersion}"
include "com.enonic.lib:lib-mustache:2.1.1"
include "com.enonic.lib:lib-http-client:3.2.2"
include "com.enonic.xp:lib-io:${xpVersion}"
include "com.enonic.lib:lib-license:3.1.0"
include "com.enonic.xp:lib-auth:${xpVersion}"
Expand Down
12 changes: 12 additions & 0 deletions modules/app/src/main/resources/admin/tools/main/main.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,18 @@
<link rel="stylesheet" type="text/css" href="{{assetsUri}}/admin/common/styles/lib.css">
<link rel="stylesheet" type="text/css" href="{{assetsUri}}/styles/contentlib.css">
<script type="text/javascript" src="{{assetsUri}}/admin/common/js/lib.js"></script>

{{#aiContentOperatorAssetsUrl}}
<!-- Append AI Content Operator -->
<link rel="stylesheet" type="text/css" href="{{aiContentOperatorAssetsUrl}}/style.css">
<script type="text/javascript" src="{{aiContentOperatorAssetsUrl}}/index.js" data-locales="{{aiLocales}}"
data-asset-url="{{aiContentOperatorAssetsUrl}}" async></script>
{{/aiContentOperatorAssetsUrl}}

{{#aiTranslatorAssetsUrl}}
<!-- Append AI Translator -->
<script type="text/javascript" src="{{aiTranslatorAssetsUrl}}/index.js" data-asset-url="{{aiTranslatorAssetsUrl}}" async></script>
{{/aiTranslatorAssetsUrl}}
</head>
<body>

Expand Down
32 changes: 24 additions & 8 deletions modules/app/src/main/resources/admin/tools/main/main.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
/*global app, resolve*/

const admin = require('/lib/xp/admin');
const appLib = require('/lib/xp/app');
const mustache = require('/lib/mustache');
const portal = require('/lib/xp/portal');
const i18n = require('/lib/xp/i18n');

exports.renderTemplate = function (path, params) {
const AI_TRANSLATOR_APP_KEY = 'com.enonic.app.ai.translator';
const AI_CONTENT_OPERATOR_APP_KEY = 'com.enonic.app.ai.contentoperator';

exports.renderTemplate = function (params) {
const view = resolve('./main.html');
const toolUri = admin.getToolUrl(app.name, 'main');
const isBrowseMode = path === toolUri;
const enableSecurityPolicy = app.config['contentSecurityPolicy.enabled'] !== 'false';

params.isBrowseMode = isBrowseMode;
const enableSecurityPolicy = app.config['contentSecurityPolicy.enabled'] !== 'false';

const response = {
contentType: 'text/html',
Expand All @@ -32,30 +33,45 @@ exports.renderTemplate = function (path, params) {
return response;
}

exports.getParams = function () {
exports.getParams = function (path) {
const toolUrlBase = admin.getToolUrl(
app.name,
'main'
);
const isBrowseMode = path === admin.getToolUrl(app.name, 'main');

const aiContentOperatorApp = appLib.get({key: AI_CONTENT_OPERATOR_APP_KEY});
const aiTranslatorApp = appLib.get({key: AI_TRANSLATOR_APP_KEY});

const isAiContentOperatorEnabled = aiContentOperatorApp != null && aiContentOperatorApp.started && !isBrowseMode;
const isAiTranslatorEnabled = aiTranslatorApp != null && aiTranslatorApp.started && !isBrowseMode;

const locales = admin.getLocales();

return {
assetsUri: portal.assetUrl({path: ''}),
appName: i18n.localize({
key: 'admin.tool.displayName',
bundles: ['i18n/phrases'],
locale: admin.getLocales()
locale: locales
}),
aiContentOperatorAssetsUrl: isAiContentOperatorEnabled ? portal.assetUrl({application: AI_CONTENT_OPERATOR_APP_KEY}) : undefined,
aiTranslatorAssetsUrl: isAiTranslatorEnabled ? portal.assetUrl({application: AI_TRANSLATOR_APP_KEY}) : undefined,
launcherPath: admin.getLauncherPath(),
configServiceUrl: portal.apiUrl({
application: app.name,
api: 'config',
}),
toolBaseUrl: toolUrlBase,
toolAppName: app.name,
isBrowseMode: isBrowseMode,
aiLocales: locales ? locales.join(',') : '',
}
}

function handleGet(req) {
return exports.renderTemplate(req.path, exports.getParams());
const params = exports.getParams(req.path);
return exports.renderTemplate(params);
}

exports.get = handleGet;
2 changes: 2 additions & 0 deletions modules/app/src/main/resources/admin/tools/main/main.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,7 @@
<api>com.enonic.xp.app.main:i18n</api>
<api>admin:widget</api>
<api>com.enonic.app.contentstudio.plus:i18n</api>
<api>com.enonic.app.ai.contentoperator:rest</api>
<api>com.enonic.app.ai.translator:rest</api>
</apis>
</tool>
15 changes: 15 additions & 0 deletions modules/app/src/main/resources/apis/config/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ function handleGet() {
app.name,
'main'
);
const sagaPollDelay = Number(app.config['openai.poll.delay']) || 0;
const sagaPollLimit = Number(app.config['openai.poll.limit']) || 0;

return {
status: 200,
contentType: 'application/json',
Expand Down Expand Up @@ -59,6 +62,18 @@ function handleGet() {
application: app.name,
api: 'export',
}),
aiContentOperatorServiceUrl: portal.apiUrl({
application: 'com.enonic.app.ai.contentoperator',
api: 'rest',
}),
aiTranslatorServiceUrl: portal.apiUrl({
application: 'com.enonic.app.ai.translator',
api: 'rest',
}),
appServiceUrl: portal.apiUrl({
application: app.name,
api: 'applications',
}),
},
theme: 'light',
/* Remove in CS/lib-admin-ui 5.0 */
Expand Down
56 changes: 56 additions & 0 deletions modules/app/src/main/resources/lib/requests.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
const utils = require('/lib/utils');
const libHttpClient = require('/lib/http-client');

function respondJson(status, body) {
return {
status: status,
contentType: 'application/json',
body: body,
};
}

exports.respondJson = respondJson;

function respondMessage(status, message) {
return respondJson(status, {
message: message,
});
}

exports.respondMessage = respondMessage;

function request(params) {
const path = params.path;
const method = params.method || 'GET';
const headers = utils.copy({
accept: 'application/json',
}, params.headers || {});
const body = params.body;

return libHttpClient.request({
url: path,
method: method,
headers: headers,
connectionTimeout: 15000,
readTimeout: 10000,
body: body ? JSON.stringify(body) : undefined,
});
}

exports.request = request;

function getRequest(path, headers) {
try {
return libHttpClient.request({
url: path,
method: 'GET',
headers: headers || {},
});
} catch (e) {
log.error('Problems with executing GET: ' + path);
log.error(e.stack);
throw e;
}
}

exports.getRequest = getRequest;
15 changes: 15 additions & 0 deletions modules/app/src/main/resources/lib/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
function copy(objA, objB) {
const newObject = {};
for (let i = 0; i < arguments.length; i++) {
let obj = arguments[i] || {};
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
newObject[key] = obj[key];
}
}
}

return newObject;
}

exports.copy = copy;
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file not shown.
8 changes: 8 additions & 0 deletions modules/lib/src/main/resources/assets/icons/icons.less
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,14 @@
}
}

.icon-copy {
.icon-studio-lib();

&::before {
content: "\e92c";
}
}

.icon-inherited(@size: 18px, @width: @size+2, @height: @size+2, @line-height: @size+4) {
.icon-down-arrow();

Expand Down
19 changes: 10 additions & 9 deletions modules/lib/src/main/resources/assets/js/app/ContentFormContext.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import {Input} from '@enonic/lib-admin-ui/form/Input';
import {Application} from '@enonic/lib-admin-ui/application/Application';
import {ApplicationKey} from '@enonic/lib-admin-ui/application/ApplicationKey';
import {PropertyPath} from '@enonic/lib-admin-ui/data/PropertyPath';
import {ContentInputTypeViewContext} from './inputtype/ContentInputTypeViewContext';
import {Content} from './content/Content';
import {Site} from './content/Site';
import {FormContext, FormContextBuilder} from '@enonic/lib-admin-ui/form/FormContext';
import {Input} from '@enonic/lib-admin-ui/form/Input';
import {ContentTypeName} from '@enonic/lib-admin-ui/schema/content/ContentTypeName';
import {Content} from './content/Content';
import {ContentId} from './content/ContentId';
import {ContentPath} from './content/ContentPath';
import {Site} from './content/Site';
import {ContentInputTypeViewContext} from './inputtype/ContentInputTypeViewContext';
import {Project} from './settings/data/project/Project';
import {ApplicationKey} from '@enonic/lib-admin-ui/application/ApplicationKey';
import {Application} from '@enonic/lib-admin-ui/application/Application';

export class ContentFormContext
extends FormContext {
Expand Down Expand Up @@ -86,7 +86,8 @@ export class ContentFormContext
return this.stoppedApplications?.find(app => app.getApplicationKey().equals(appKey));
}

createInputTypeViewContext(inputTypeConfig: object, parentPropertyPath: PropertyPath, input: Input): ContentInputTypeViewContext {
createInputTypeViewContext(inputTypeConfig: ContentInputTypeViewContext['inputConfig'], parentPropertyPath: PropertyPath,
input: Input): ContentInputTypeViewContext {
const viewContext = {
formContext: this,
input: input,
Expand All @@ -96,7 +97,7 @@ export class ContentFormContext
content: this.getPersistedContent(),
project: this.getProject(),
applicationKey: this.applicationKey
} as ContentInputTypeViewContext;
} satisfies ContentInputTypeViewContext;

this.contentUpdatedListeners.push(content => {
viewContext.content = content;
Expand All @@ -114,7 +115,7 @@ export class ContentFormContext
.setApplicationKey(this.applicationKey)
.setFormState(this.getFormState())
.setShowEmptyFormItemSetOccurrences(this.getShowEmptyFormItemSetOccurrences())
.setValidationErrors(this.getValidationErrors()) as ContentFormContextBuilder;
.setValidationErrors(this.getValidationErrors());
}

static create(): ContentFormContextBuilder {
Expand Down
12 changes: 7 additions & 5 deletions modules/lib/src/main/resources/assets/js/app/TooltipHelper.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {StyleHelper} from '@enonic/lib-admin-ui/StyleHelper';
import {ElementRemovedEvent} from '@enonic/lib-admin-ui/dom/ElementRemovedEvent';
import {ElementRegistry} from '@enonic/lib-admin-ui/dom/ElementRegistry';
import {Element} from '@enonic/lib-admin-ui/dom/Element';
import {ElementRegistry} from '@enonic/lib-admin-ui/dom/ElementRegistry';
import {ElementRemovedEvent} from '@enonic/lib-admin-ui/dom/ElementRemovedEvent';
import {StyleHelper} from '@enonic/lib-admin-ui/StyleHelper';

export class TooltipHelper {

Expand Down Expand Up @@ -76,8 +76,10 @@ export class TooltipHelper {

function removeTooltipOnClick(e: JQuery.MouseEventBase): void {
setTimeout(() => {
const target = e.target || e.currentTarget;
const canRemove = !lastTarget || lastTarget.isEqualNode(target) || lastTarget.contains(target);
const canRemove = !lastTarget ||
lastTarget.isEqualNode(e.target) ||
lastTarget.isEqualNode(e.currentTarget) ||
lastTarget.contains(e.target);
if (canRemove) {
removeTooltip(e);
}
Expand Down
Loading
Loading