Skip to content

Commit

Permalink
memore UI
Browse files Browse the repository at this point in the history
  • Loading branch information
GiordanoT committed Sep 21, 2023
1 parent ba5bac2 commit e730ec2
Show file tree
Hide file tree
Showing 26 changed files with 246 additions and 207 deletions.
8 changes: 8 additions & 0 deletions src/common/U.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,14 @@ export class U {
views.push('Pointer_ViewObject');
views.push('Pointer_ViewValue');
views.push('Pointer_ViewDefaultPackage');
views.push('Pointer_ViewVoid');
views.push('Pointer_ViewEdgeAssociation');
views.push('Pointer_ViewEdgeDependency');
views.push('Pointer_ViewEdgeInheritance');
views.push('Pointer_ViewEdgeAggregation');
views.push('Pointer_ViewEdgeComposition');
views.push('Pointer_ViewEdgePoint');
views.push('Pointer_ViewEdgePointSVG');
return views;
}

Expand Down
2 changes: 1 addition & 1 deletion src/components/abstract/DockLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -235,10 +235,10 @@ class DockLayoutComponent extends PureComponent<AllProps, ThisState>{
// this.test,
// this.iotEditor,
this.structureEditor,
this.styleEditor,
this.treeEditor,
this.viewsEditor,
this.viewpointEditor,
// this.styleEditor,
this.console
];
layout.dockbox.children.push({tabs});
Expand Down
2 changes: 1 addition & 1 deletion src/components/abstract/tabs/InfoTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {DState, LGraph, LModel, DGraph, DModelElement, LModelElement} from "../.
import {DefaultNode} from "../../../joiner/components";
import ToolBar from "../../toolbar/ToolBar";
import PendingEdge from "../../../graph/edge/PendingEdge";
import ContextMenu from "../../toolbar/ContextMenu";
import ContextMenu from "../../contextMenu/ContextMenu";
import EdgesManager from "../../../graph/edges/EdgesManager";


Expand Down
2 changes: 1 addition & 1 deletion src/components/abstract/tabs/MetamodelTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {DState, CreateElementAction, DGraph, LGraph, LModel} from "../../../join
import {DefaultNode} from "../../../joiner/components";
import ToolBar from "../../toolbar/ToolBar";
import PendingEdge from "../../../graph/edge/PendingEdge";
import ContextMenu from "../../toolbar/ContextMenu";
import ContextMenu from "../../contextMenu/ContextMenu";
import EdgesManager from "../../../graph/edges/EdgesManager";

function MetamodelTabComponent(props: AllProps) {
Expand Down
2 changes: 1 addition & 1 deletion src/components/abstract/tabs/ModelTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {DState, LGraph, LModel, DGraph, DModelElement, LModelElement, CreateElem
import {DefaultNode} from "../../../joiner/components";
import ToolBar from "../../toolbar/ToolBar";
import PendingEdge from "../../../graph/edge/PendingEdge";
import ContextMenu from "../../toolbar/ContextMenu";
import ContextMenu from "../../contextMenu/ContextMenu";
import EdgesManager from "../../../graph/edges/EdgesManager";


Expand Down
2 changes: 1 addition & 1 deletion src/components/abstract/tabs/TestTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ type AllProps = OwnProps & StateProps & DispatchProps;

function mapStateToProps(state: DState, ownProps: OwnProps): StateProps {
const ret: StateProps = {} as any;
ret.selected = LModelElement.fromPointer(state.selected[DUser.current] as any);
ret.selected = null;
return ret;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, {Dispatch, ReactElement, ReactNode, useEffect} from "react";
import {connect} from "react-redux";
import "./style.scss";
import {CreateElementAction, SetRootFieldAction} from "../../redux/action/action";
import React, {Dispatch, ReactElement, ReactNode, useEffect} from 'react';
import {connect} from 'react-redux';
import './style.scss';
import {CreateElementAction, SetRootFieldAction} from '../../redux/action/action';
import {
DValue,
DViewElement,
Expand All @@ -12,9 +12,10 @@ import {
LPackage,
LUser,
LValue, DState,
} from "../../joiner";
import MemoRec from "../../memorec/api";
import {useStateIfMounted} from "use-state-if-mounted";
} from '../../joiner';
import MemoRec from '../../memorec/api';
import {useStateIfMounted} from 'use-state-if-mounted';
import ModellingIcon from "../forEndUser/ModellingIcon";

function ContextMenuComponent(props: AllProps) {

Expand All @@ -35,22 +36,22 @@ function ContextMenuComponent(props: AllProps) {
const close = () => {
setSuggestedName('');
setMemorec(null);
SetRootFieldAction.new("contextMenu", {display: false, x: 0, y: 0});
SetRootFieldAction.new('contextMenu', {display: false, x: 0, y: 0});
}
const addView = () => {
if(me) {
const jsx =`<div className={'root bg-white'}>Hello World!</div>`;
const dView: DViewElement = DViewElement.new(me.name + 'View', jsx);
switch(me.className) {
case 'DClass':
dView.query = `context DObject inv: self.instanceof.name = '${me.name}'`;
dView.query = `context DObject inv: self.instanceof.id = '${me.id}'`;
break;
case 'DAttribute':
case 'DReference':
dView.query = `context DValue inv: self.instanceof.name = '${me.name}'`;
dView.query = `context DValue inv: self.instanceof.id = '${me.id}'`;
break;
case 'DObject':
dView.query = `context DObject inv: self.id = '${me.id}'`;
default:
dView.query = `context ${me.className} inv: self.id = '${me.id}'`;
break;
}
CreateElementAction.new(dView);
Expand Down Expand Up @@ -86,55 +87,71 @@ function ContextMenuComponent(props: AllProps) {
close();
}
if(display && me && node) {
jsxList.push(<div className={"col title text-center"}>{me.className}</div>);
jsxList.push(<hr />);
jsxList.push(<div className={'mt-1 col text-center'}><b>{me.className}</b></div>);
jsxList.push(<hr className={'my-1'} />);

/* Memorec */
if(me.className === 'DClass')
jsxList.push(<div onClick={structuralFeature} className={"col item"}>AI Suggest <i
className="bi bi-arrow-right-short"></i></div>);
jsxList.push(<div onClick={structuralFeature} className={'col item'}>AI Suggest <i
className='bi bi-arrow-right-short'></i></div>);
if(me.className === 'DPackage')
jsxList.push(<div onClick={classifier} className={"col item"}>AI Suggest</div>);
jsxList.push(<div onClick={() => {close(); node.zIndex += 1;}} className={"col item"}>Up</div>);
jsxList.push(<div onClick={() => {close(); node.zIndex -= 1;}} className={"col item"}>Down</div>);
jsxList.push(<div onClick={() => {close(); addView();}} className={"col item"}>Add View</div>);
jsxList.push(<div onClick={() => {close(); me?.delete();}} className={"col item"}>Delete</div>);
jsxList.push(<div onClick={classifier} className={'col item'}>
AI Suggest
<i className={'ms-1 bi bi-arrow-right'}></i>
</div>);
jsxList.push(<div onClick={() => {close(); node.zIndex += 1;}} className={'col item'}>Up</div>);
jsxList.push(<div onClick={() => {close(); node.zIndex -= 1;}} className={'col item'}>Down</div>);
jsxList.push(<div onClick={() => {close(); addView();}} className={'col item'}>Add View</div>);
jsxList.push(<div onClick={() => {close(); me?.delete();}} className={'col item'}>Delete</div>);
switch (me.className) {
case 'DValue': if ((me as any as LValue).instanceof) jsxList.pop(); break;
case 'DClass':
jsxList.push(<div onClick={() => {
close();
SetRootFieldAction.new('isEdgePending', {user: user.id, source: me.id});
}} className={"col item"}>Extend</div>);
}} className={'col item'}>Extend</div>);
break;
}
}

return(<>

<div className={"context-menu round"} style={{top: position.y - 100, left: position.x - 10}}>
{jsxList.map((jsx, index) => { return <div key={index}>{jsx}</div>; })}
<div className={'context-menu round'} style={{top: position.y - 100, left: position.x - 10}}>
{jsxList.map((jsx, index) => {return <div key={index}>{jsx}</div>})}
</div>

{(memorec) && <div className={"context-menu round"} style={{top: position.y - 100, left: position.x + 130}}>

{(memorec) && <div className={'context-menu round'} style={{overflow: 'auto', maxHeight: '12em', top: position.y - 100, left: position.x + 130}}>
{(memorec && memorec.data?.map((obj, index) => {
return (<div key={index}>
<div className={"col item2"} onClick={() => setSuggestedName(obj.recommendedItem)}>
{obj.recommendedItem} : {Math.round(obj.score * 100) / 100}
<div className={'col item d-block'} onClick={e => setSuggestedName(obj.recommendedItem)}>
{obj.recommendedItem} :
<span className={'ms-1 text-primary'}>{Math.round(obj.score * 100) / 100}</span>
</div>
</div>)
})) }

}))}
</div>}
{(memorec && suggestedName) && <div className={"context-menu round"} style={{top: position.y - 100, left: position.x + 270}}>

{(memorec?.type === 'class') ? <>
<div> <div className={'col item2'} onClick={() =>suggestOnClass(true)} >attribute</div> </div>
<div><div className={'col item2'} onClick={() =>suggestOnClass(false)} >reference</div> </div>
</> : <div> <div className={'col item2'} onClick={() =>suggestOnPackage()}> class </div> </div>}
</div>
}
{(memorec && suggestedName) && <div className={'memorec-overlay'}>
<div tabIndex={-1} onBlur={e => close()} className={'memorec-popup'}>
<div className={'d-block text-center mb-1'}>Add <b>{suggestedName}</b> as:</div>
{(memorec.type === 'class') ? <>
<div tabIndex={-1} onClick={e =>suggestOnClass(true)} className={'d-flex memorec-button'}>
<ModellingIcon className={'my-auto'} name={'attribute'} />
<span className={'ms-2 my-auto'}>Attribute</span>
</div>
<div tabIndex={-1} onClick={e =>suggestOnClass(false)} className={'d-flex memorec-button mt-1'}>
<ModellingIcon className={'my-auto'} name={'reference'} />
<span className={'ms-2 my-auto'}>Reference</span>
</div>
</> :
<div tabIndex={-1} onClick={e =>suggestOnPackage()} className={'d-flex memorec-button mt-1'}>
<ModellingIcon className={'my-auto'} name={'class'} />
<span className={'ms-2 my-auto'}>Class</span>
</div>
}
<div className={'d-flex memorec-button mt-3'} tabIndex={-1} onClick={e => close()}>
<span className={'mx-auto text-danger'}>Close</span>
</div>
</div>
</div>}
</>);
}
interface OwnProps {}
Expand Down
52 changes: 52 additions & 0 deletions src/components/contextMenu/style.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
.context-menu {
position: absolute;
z-index: 999; top: 9%;
box-shadow: 0 0 2px #C0C0C0;
background: whitesmoke;
border-radius: 4px;
border-style: solid;
border-width: 1px;
border-color: lightgray;
padding: 3px;
}

.context-menu > div >.item {
cursor: pointer;
padding: 7px 30px 7px 30px;
font-size: 12px;
}

.context-menu > div > .item:hover {
background-color: #e0e0e0;
}

.memorec-overlay {
position: absolute;
height: 100%;
width: 100%;
top: 0; left: 0;
z-index: 999;
background-color: rgba(0, 0, 0, 0.4);
}
.memorec-popup {
position: absolute;
z-index: 999;
background: whitesmoke;
border-radius: 4px;
border-style: solid;
border-width: 1px;
border-color: lightgray;
left: 50%;
top: 50%;
transform: translate(-50%,-50%);
padding: 25px;
}
.memorec-button {
cursor: pointer;
background: white;
border-radius: 4px;
border-style: solid;
border-width: 1px;
border-color: lightgray;
padding: 5px;
}
77 changes: 41 additions & 36 deletions src/components/forEndUser/Input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,17 @@ import {useStateIfMounted} from "use-state-if-mounted";
function InputComponent(props: AllProps) {
// todo: data can be injected with UX, if field is present, can take type from a metainfo like __info_of__
const data = props.data;
const selected = props.selected;
// const selected = props.selected;
const fathers = U.fatherChain(data as LModelElement);
let editable = true;

/* Uncomment this when we have user authentication: if a user is on a ME, it cannot be edited.
for(let father of fathers) {
const user = Object.keys(selected).find(key => selected[key]?.id === father);
if(user && user !== DUser.current) editable = false;
if(!editable) break;
}
*/

const getter = props.getter;
const setter = props.setter;
Expand Down Expand Up @@ -101,7 +104,7 @@ function InputComponent(props: AllProps) {
let className = (props as any).className || '';
let style = (props as any).style || {};
props = {...props, className:'', style:{}} as any;
let input = <input key={`${field}.${data.id}`} spellCheck={false} readOnly={readOnly || !editable} className={css + inputClassName}
let input = <input key={`${field}.${data.id}`} spellCheck={false} readOnly={readOnly || (!editable && false)} className={css + inputClassName}
type={type} value={value} onChange={change} onBlur={blur}
checked={(['checkbox', 'radio'].includes(type)) ? !!value : undefined} />

Expand Down Expand Up @@ -130,58 +133,60 @@ function InputComponent(props: AllProps) {
}
InputComponent.cname = "InputComponent";
export interface InputOwnProps {
data: LPointerTargetable | DPointerTargetable | Pointer<DPointerTargetable, 1, 1, LPointerTargetable>;
field: string;
getter?: (data: LPointerTargetable) => string;
setter?: (value: string|boolean) => void;
label?: string;
jsxLabel?: ReactNode;
type?: 'checkbox'|'color'|'date'|'datetime-local'|'email'|'file'|'image'|'month'|
'number'|'password'|'radio'|'range'|'tel'|'text'|'time'|'url'|'week';
readonly?: boolean;
tooltip?: string | boolean | ReactElement;
hidden?: boolean;
autosize?: boolean;
inputClassName?: string;
asLabel?: boolean;
key?: React.Key | null;
data: LPointerTargetable | DPointerTargetable | Pointer<DPointerTargetable, 1, 1, LPointerTargetable>;
field: string;
getter?: (data: LPointerTargetable) => string;
setter?: (value: string|boolean) => void;
label?: string;
jsxLabel?: ReactNode;
type?: 'checkbox'|'color'|'date'|'datetime-local'|'email'|'file'|'image'|'month'|
'number'|'password'|'radio'|'range'|'tel'|'text'|'time'|'url'|'week';
readonly?: boolean;
tooltip?: string | boolean | ReactElement;
hidden?: boolean;
autosize?: boolean;
inputClassName?: string;
asLabel?: boolean;
key?: React.Key | null;
}
interface StateProps {
data: LPointerTargetable & GObject;
selected: Dictionary<Pointer<DUser>, LModelElement|null>;

data: LPointerTargetable & GObject;
// selected: Dictionary<Pointer<DUser>, LModelElement|null>;
}
interface DispatchProps { }
type AllProps = Overlap<InputOwnProps, Overlap<StateProps, DispatchProps>>;


function mapStateToProps(state: DState, ownProps: InputOwnProps): StateProps {
const ret: StateProps = {} as any;
const pointer: Pointer = typeof ownProps.data === 'string' ? ownProps.data : ownProps.data.id;
ret.data = LPointerTargetable.fromPointer(pointer);
const selected = state.selected;
ret.selected = {};
for(let user of Object.keys(selected)) {
const pointer = selected[user];
if(pointer) ret.selected[user] = LModelElement.fromPointer(pointer);
else ret.selected[user] = null;
}
return ret;
const ret: StateProps = {} as any;
const pointer: Pointer = typeof ownProps.data === 'string' ? ownProps.data : ownProps.data.id;
ret.data = LPointerTargetable.fromPointer(pointer);
/*
const selected = state.selected;
ret.selected = {};
for(let user of Object.keys(selected)) {
const pointer = selected[user];
if(pointer) ret.selected[user] = LModelElement.fromPointer(pointer);
else ret.selected[user] = null;
}
*/
return ret;
}

function mapDispatchToProps(dispatch: Dispatch<any>): DispatchProps {
const ret: DispatchProps = {};
return ret;
const ret: DispatchProps = {};
return ret;
}

export const InputConnected = connect<StateProps, DispatchProps, InputOwnProps, DState>(
mapStateToProps,
mapDispatchToProps
mapStateToProps,
mapDispatchToProps
)(InputComponent);


export function Input(props: InputOwnProps, children: (string | React.Component)[] = []): ReactElement {
return <InputConnected {...{...props, children}} />;
return <InputConnected {...{...props, children}} />;
}

InputComponent.cname = "InputComponent";
Expand Down
Loading

0 comments on commit e730ec2

Please sign in to comment.