Skip to content
Snippets Groups Projects
Commit 8d812efd authored by chris's avatar chris
Browse files

rename button

parent a2c32781
No related branches found
No related tags found
1 merge request!466Chatgpt demo
Showing
with 4 additions and 283 deletions
......@@ -22,12 +22,11 @@ import {
EssayService,
MatchingService,
MultipleDropDownService,
AnyStyleService,
ExternalAPIContentService,
} from 'wax-prosemirror-services';
import { DefaultSchema } from 'wax-prosemirror-core';
import invisibles, { hardBreak } from '@guardian/prosemirror-invisibles';
const API_KEY = '';
async function ExternalAPIContentTransformation(prompt) {
const response = await fetch('https://api.openai.com/v1/chat/completions', {
......@@ -125,7 +124,7 @@ export default {
toolGroups: ['MultipleDropDown'],
},
],
AnyStyleService: {
ExternalAPIContentService: {
ExternalAPIContentTransformation: ExternalAPIContentTransformation,
},
......@@ -135,7 +134,7 @@ export default {
PmPlugins: [columnResizing(), tableEditing(), invisibles([hardBreak()])],
services: [
new AnyStyleService(),
new ExternalAPIContentService(),
new MatchingService(),
new FillTheGapQuestionService(),
new MultipleChoiceQuestionService(),
......
......@@ -39,7 +39,7 @@ export { default as MultipleDropDownService } from './src/MultipleDropDownServic
export { default as OENContainersService } from './src/OENContainersService/OENContainersService';
export { default as YjsService } from './src/YjsService/YjsService';
export { default as AnyStyleService } from './src/AnyStyleService/AnyStyleService';
export { default as ExternalAPIContentService } from './src/ExternalAPIContentService/ExternalAPIContentService';
/*
ToolGroups
*/
......
import { Service } from 'wax-prosemirror-core';
import AnyStyleTool from './AnyStyleTool';
import AnyStyleToolGroupService from './AnyStyleToolGroupService/AnyStyleToolGroupService';
import AnyStylePlaceHolderPlugin from './plugins/AnyStylePlaceHolderPlugin';
import './anyStyle.css';
class AnyStyleService extends Service {
name = 'AnyStyleService';
boot() {
this.app.PmPlugins.add(
'anyStylePlaceHolder',
AnyStylePlaceHolderPlugin('anyStylePlaceHolder'),
);
}
register() {
this.container.bind('AnyStyleTool').to(AnyStyleTool);
}
dependencies = [new AnyStyleToolGroupService()];
}
export default AnyStyleService;
import React, { useContext } from 'react';
import { v4 as uuidv4 } from 'uuid';
import { isEmpty } from 'lodash';
import { injectable } from 'inversify';
import { WaxContext, Commands, Tools } from 'wax-prosemirror-core';
import AnyStyleButton from './components/AnyStyleButton';
import replaceText from './replaceText';
@injectable()
class AnyStyleTool extends Tools {
title = 'ChatGPT';
name = 'ChatGPT';
label = 'ChatGPT';
get run() {
return true;
}
select = activeView => {
return true;
};
get enable() {
return state => {
return true;
};
}
renderTool(view) {
if (isEmpty(view)) return null;
const context = useContext(WaxContext);
const anyStyle = replaceText(
view,
this.config.get('config.AnyStyleService')
.ExternalAPIContentTransformation,
this.pmplugins.get('anyStylePlaceHolder'),
context,
);
return this.isDisplayed() ? (
<AnyStyleButton
anyStyle={anyStyle}
item={this.toJSON()}
key={uuidv4()}
view={view}
/>
) : null;
}
// renderTool(view) {
// if (isEmpty(view)) return null;
// const context = useContext(WaxContext);
// const upload = fileUpload(
// view,
// this.config.get('fileUpload'),
// this.pmplugins.get('imagePlaceHolder'),
// context,
// );
// return this.isDisplayed() ? (
// <ImageUpload
// fileUpload={upload}
// item={this.toJSON()}
// key={uuidv4()}
// view={view}
// />
// ) : null;
// }
}
export default AnyStyleTool;
import { injectable, inject } from 'inversify';
import { ToolGroup } from 'wax-prosemirror-core';
@injectable()
class Anystyle extends ToolGroup {
tools = [];
constructor(@inject('AnyStyleTool') anyStyleTool) {
super();
this.tools = [anyStyleTool];
}
}
export default Anystyle;
import { Service } from 'wax-prosemirror-core';
import AnyStyle from './AnyStyle';
class AnyStyleToolGroupService extends Service {
register() {
this.container.bind('AnyStyle').to(AnyStyle);
}
}
export default AnyStyleToolGroupService;
placeholder-any-style:before {
position: relative;
top: 3px;
content: url("data:image/svg+xml; utf8, <svg xmlns='http://www.w3.org/2000/svg' height='24' width='24'><path d='M8 20h8v-3q0-1.65-1.175-2.825Q13.65 13 12 13q-1.65 0-2.825 1.175Q8 15.35 8 17Zm-4 2v-2h2v-3q0-1.525.713-2.863Q7.425 12.8 8.7 12q-1.275-.8-1.987-2.138Q6 8.525 6 7V4H4V2h16v2h-2v3q0 1.525-.712 2.862Q16.575 11.2 15.3 12q1.275.8 1.988 2.137Q18 15.475 18 17v3h2v2Z' /></svg>");
}
\ No newline at end of file
/* eslint react/prop-types: 0 */
import React, { useContext, useMemo, useEffect } from 'react';
import { WaxContext, DocumentHelpers, MenuButton } from 'wax-prosemirror-core';
import { TextSelection } from 'prosemirror-state';
const AnyStyleButton = ({ view = {}, item, anyStyle }) => {
const { active, icon, label, run, select, title } = item;
const {
app,
pmViews: { main },
activeViewId,
activeView,
} = useContext(WaxContext);
const { state } = view;
const handleMouseDown = (e, editorState) => {
e.preventDefault();
const {
selection: { $from, $to },
} = editorState;
/* this is the content that we have to get from the selection */
const textSelection = new TextSelection($from, $to);
const content = textSelection.content();
anyStyle(content.content.content[0].textContent);
};
useEffect(() => {}, []);
const isActive = !!active(state, activeViewId);
let isDisabled = !select(state, activeViewId, activeView);
const isEditable = main.props.editable(editable => {
return editable;
});
if (!isEditable) isDisabled = true;
const AnyStyleButtonComponent = useMemo(
() => (
<MenuButton
active={isActive || false}
disabled={isDisabled}
iconName={icon}
label={label}
onMouseDown={e => handleMouseDown(e, view.state, view.dispatch)}
title={title}
/>
),
[isActive, isDisabled],
);
return AnyStyleButtonComponent;
};
export default AnyStyleButton;
/* eslint-disable no-param-reassign */
import { Plugin, PluginKey } from 'prosemirror-state';
import { Decoration, DecorationSet } from 'prosemirror-view';
export default key =>
new Plugin({
key: new PluginKey(key),
state: {
init: function init() {
return DecorationSet.empty;
},
apply: function apply(tr, set) {
// Adjust decoration positions to changes made by the transaction
set = set.map(tr.mapping, tr.doc);
// See if the transaction adds or removes any placeholders
const action = tr.getMeta(this);
if (action && action.add) {
const widget = document.createElement('placeholder-any-style');
const deco = Decoration.widget(action.add.pos, widget, {
id: action.add.id,
});
set = set.add(tr.doc, [deco]);
} else if (action && action.remove) {
set = set.remove(
set.find(null, null, spec => spec.id === action.remove.id),
);
}
return set;
},
},
props: {
decorations: function decorations(state) {
return this.getState(state);
},
},
});
import { v4 as uuidv4 } from 'uuid';
import { DOMParser } from 'prosemirror-model';
const findPlaceholder = (state, id, placeholderPlugin) => {
const decos = placeholderPlugin.getState(state);
const found = decos.find(null, null, spec => spec.id === id);
return found.length ? found[0].from : null;
};
const elementFromString = string => {
const wrappedValue = `<body>${string}</body>`;
return new window.DOMParser().parseFromString(wrappedValue, 'text/html').body;
};
export default (
view,
ExternalAPIContentTransformation,
placeholderPlugin,
context,
) => data => {
const { state } = view;
// A fresh object to act as the ID for this upload
const id = {};
// Replace the selection with a placeholder
const { tr } = state;
if (!tr.selection.empty) tr.deleteSelection();
tr.setMeta(placeholderPlugin, {
add: { id, pos: tr.selection.from },
});
view.dispatch(tr);
ExternalAPIContentTransformation(data).then(
text => {
const pos = findPlaceholder(view.state, id, placeholderPlugin);
// If the content around the placeholder has been deleted, drop
// the image
if (pos == null) {
return;
}
const parser = DOMParser.fromSchema(
context.pmViews.main.state.config.schema,
);
const parsedContent = parser.parse(elementFromString(text));
// Otherwise, insert it at the placeholder's position, and remove
// the placeholder
context.pmViews[context.activeViewId].dispatch(
context.pmViews[context.activeViewId].state.tr
.replaceWith(pos, pos, parsedContent)
.setMeta(placeholderPlugin, { remove: { id } }),
);
},
() => {
// On failure, just clean up the placeholder
view.dispatch(tr.setMeta(placeholderPlugin, { remove: { id } }));
},
);
};
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment