소스 검색

adds primitive delta demo description

Alexander Raschke 2 년 전
부모
커밋
49f960b401
4개의 변경된 파일203개의 추가작업 그리고 111개의 파일을 삭제
  1. 6 1
      src/frontend/demo_editor.tsx
  2. 188 106
      src/frontend/demo_pd.tsx
  3. 2 1
      src/frontend/versioned_model.tsx
  4. 7 3
      src/frontend/welcome.tsx

+ 6 - 1
src/frontend/demo_editor.tsx

@@ -22,6 +22,11 @@ export const demo_Editor_description =
             left-clicking on the grey area with the alt-key pressed (see also the small info in the upper right corner
             of each canvas).
         </Text>
+        <Text>
+            In this demo, the editable state graph of the "Primitive Delta"-demo is replaced by a Rountangle Editor.
+            Again, any action in the Rountangle Editor results in a set of primitive deltas (shown in the center) that are applied to the (empty) state graph (on the right).
+            Note that this state graph is no longer (directly) editable. The current model state is visualized in the Rountangle Editor from which the user interaction originated.
+        </Text>
         <Actionblock>
             1. Create a rountangle!
         </Actionblock>
@@ -56,7 +61,7 @@ export const demo_Editor_description =
             In the "Delta (L1)" and "Delta (L0)" tabs, the deltas corresponding to the current version are also highlighted.
         </Resultblock>
         <Text>
-            That's it for now! Feel free to play around with the editor and watch the changes in the other views. If you want to know more details about how the deltas work, please continue with the next demo "Primitive Delta".
+            Feel free to play around with the editor and watch the changes in the other views.
         </Text>
     </>;
 

+ 188 - 106
src/frontend/demo_pd.tsx

@@ -1,9 +1,24 @@
 import * as React from "react";
 import * as Icons from "@tabler/icons";
-import {Title, Text, Grid, Button, SimpleGrid, Group, Center, ScrollArea, Card, CloseButton, Divider, Space} from "@mantine/core";
+import {
+    Title,
+    Text,
+    Grid,
+    Button,
+    SimpleGrid,
+    Group,
+    Center,
+    ScrollArea,
+    Card,
+    CloseButton,
+    Divider,
+    Space
+} from "@mantine/core";
 
 import {PrimitiveRegistry} from "../onion/primitive_delta";
 import {mockUuid} from "../onion/test_helpers";
+import {GrContactInfo} from "react-icons/all";
+import {Actionblock, Resultblock} from "./blocks";
 
 export const demo_PD_description =
     <>
@@ -11,122 +26,189 @@ export const demo_PD_description =
             Primitive deltas
         </Title>
         <Text>
-            In this demo, we restrict the view to a - in this case directly manipulatable - state graph, history, and primitive deltas.
+            On the right side you will see three canvases "State", "History", and "Deltas(L0)".
+        </Text>
+        <Text>
+            "State" shows the state graph, which represents the state of our model. If you now e.g. click with the right
+            mouse button on a free area in the canvas, then this action is converted into a "Delta". The set of deltas
+            is then in turn applied to the state grap, resulting in the visualization of a new node.
         </Text>
+        <Actionblock>
+            1. Click with your right mouse button into the "State" canvas!
+        </Actionblock>
+        <Resultblock>
+            A "NEW(0)"-delta occurs in the "Delta(L0)" canvas.
+        </Resultblock>
+        <Resultblock>
+            The "0" corresponds to the ID of the created node.
+        </Resultblock>
+        <Resultblock>
+            A new version appears in the "History" canvas that depends on the previous (initial version).
+        </Resultblock>
+        <Actionblock>
+            2. Hover with your mouse over the circle with an (i) inside the "State" canvas!
+        </Actionblock>
+        <Resultblock>
+            A tooltip with information about possible interactions of this canvas is shown.
+        </Resultblock>
+        <Actionblock>
+            3. Create an edge to a value by right-dragging from the created node into the canvas!
+        </Actionblock>
+        <Resultblock>
+            The generated delta "EDG(..)" depends on the creation (NEW(0)) of the node from which the edge originates.
+        </Resultblock>
+        This detailed recording of each action allows to easily detect conflicts between two versions or to merge
+        conflict-free versions.
+        <Actionblock>
+            4. Press the button "Undo" once!
+        </Actionblock>
+        <Resultblock>
+            The version before creating the edge is selected in the "History" canvas.
+        </Resultblock>
+        <Resultblock>
+            In the "Delta"-view the set of Deltas that are associated with the currently selected version is drawn with
+            a bold border.
+        </Resultblock>
+        <Actionblock>
+            5. Press the "Clone"-Button and enter a new branch name!
+        </Actionblock>
+        <Actionblock>
+            6. Delete the node in the cloned branch by a click with the middle mouse button!
+        </Actionblock>
+        <Actionblock>
+            7. Press the "Redo"-Button in the "master"-branch!
+        </Actionblock>
+        <Actionblock>
+            8. Press the "Union"-Button in the lower branch!
+        </Actionblock>
+        <Resultblock>
+            While merging the sets of Deltas of both branches, the framework recognizes a deletion-update conflict
+            between the previously created edge and the deletion of the node from which the edge originated (shown by
+            the red line between them).
+        </Resultblock>
+        <Resultblock>
+            In the History, you can now choose between two "Restore" actions, but they cannot be applied simultaneously due to the conflict.
+        </Resultblock>
+
     </>;
 
 
 import {
-  newVersionedModel,
-  VersionedModelState,
+    newVersionedModel,
+    VersionedModelState,
 } from "./versioned_model";
 
 export function getDemoPD() {
-  const primitiveRegistry = new PrimitiveRegistry();
-  const generateUUID = mockUuid();
-
-  const model = newVersionedModel({readonly: false, generateUUID, primitiveRegistry});
-
-  const initialState: [string, VersionedModelState, any][] = [
-    ["master", model.initialState, model],
-  ];
-
-  return function() {
-    const [globalState, setGlobalState] = React.useState<[string, VersionedModelState, any][]>(initialState);
-
-    const getSetBranchState = i => {
-      return callback => {
-        setGlobalState(prevGlobalState => {
-          const copy = prevGlobalState.slice();
-          const [branchName, prevBranchState, m] = copy[i];
-          copy[i] = [branchName, callback(prevBranchState), m];
-          return copy;
-        });
-      };
-    }
-
-    return <>{ globalState.map(([branchName, branchState, {getCurrentVersion, getReducer, getReactComponents}], i) => {
-        const setBranchState = getSetBranchState(i);
-
-        const reducer = getReducer(setBranchState);
-
-        const components = getReactComponents(branchState, {
-          onUserEdit: reducer.createAndGotoNewVersion,
-          onUndoClicked: reducer.undo,
-          onRedoClicked: reducer.redo,
-          onVersionClicked: reducer.gotoVersion,
-        });
+    const primitiveRegistry = new PrimitiveRegistry();
+    const generateUUID = mockUuid();
+
+    const model = newVersionedModel({readonly: false, generateUUID, primitiveRegistry});
+
+    const initialState: [string, VersionedModelState, any][] = [
+        ["master", model.initialState, model],
+    ];
+
+    return function () {
+        const [globalState, setGlobalState] = React.useState<[string, VersionedModelState, any][]>(initialState);
+
+        const getSetBranchState = i => {
+            return callback => {
+                setGlobalState(prevGlobalState => {
+                    const copy = prevGlobalState.slice();
+                    const [branchName, prevBranchState, m] = copy[i];
+                    copy[i] = [branchName, callback(prevBranchState), m];
+                    return copy;
+                });
+            };
+        }
 
-        const unionClicked = () => {
-          const [mergeWithBranchName, mergeWithBranchState, {getReducer: getOtherReducer}] = globalState[i-1];
-          const otherReducer = getOtherReducer(getSetBranchState(i-1));
-          const addRecursive = ([version, delta, _]) => {
-            if (version.parents.length > 0) {
-              addRecursive(version.parents[0])
+        return <>{globalState.map(([branchName, branchState, {
+            getCurrentVersion,
+            getReducer,
+            getReactComponents
+        }], i) => {
+            const setBranchState = getSetBranchState(i);
+
+            const reducer = getReducer(setBranchState);
+
+            const components = getReactComponents(branchState, {
+                onUserEdit: reducer.createAndGotoNewVersion,
+                onUndoClicked: reducer.undo,
+                onRedoClicked: reducer.redo,
+                onVersionClicked: reducer.gotoVersion,
+            });
+
+            const unionClicked = () => {
+                const [mergeWithBranchName, mergeWithBranchState, {getReducer: getOtherReducer}] = globalState[i - 1];
+                const otherReducer = getOtherReducer(getSetBranchState(i - 1));
+                const addRecursive = ([version, delta, _]) => {
+                    if (version.parents.length > 0) {
+                        addRecursive(version.parents[0])
+                    }
+                    otherReducer.addDeltasAndVersion(delta.deltas, delta.getDescription(), version.hash);
+                }
+                addRecursive(getCurrentVersion().parents[0]);
+                setGlobalState(prevGlobalState => [
+                    ...prevGlobalState.slice(0, i),
+                    ...prevGlobalState.slice(i + 1),
+                ]);
             }
-            otherReducer.addDeltasAndVersion(delta.deltas, delta.getDescription(), version.hash);
-          }
-          addRecursive(getCurrentVersion().parents[0]);
-          setGlobalState(prevGlobalState => [
-            ...prevGlobalState.slice(0,i),
-            ...prevGlobalState.slice(i+1),
-          ]);
-        }
 
-        const cloneClicked = () => {
-          const newBranchName = prompt("Branch name: (ESC to cancel)", "branch");
-          if (newBranchName === null) {
-            return;
-          }
-          if (globalState.some(([existingBranchName]) => existingBranchName === newBranchName)) {
-            alert("Branch with this name already exists!");
-            return;
-          }
-          const newModel = newVersionedModel({readonly: false, generateUUID, primitiveRegistry});
-          const newBranchState = newModel.initialState;
-
-          setGlobalState(prevGlobalState => [
-            ...prevGlobalState.slice(0,i+1),
-            [newBranchName, newBranchState, newModel],
-            ...prevGlobalState.slice(i+1),
-          ]);
-
-          const setNewBranchState = getSetBranchState(i+1);
-
-          const reducer = newModel.getReducer(setNewBranchState);
-          const compositeDeltas = [...getCurrentVersion()].reverse();
-          compositeDeltas.forEach((c: any) => {
-            reducer.createAndGotoNewVersion(c.deltas, c.getDescription());
-          });
-        }
+            const cloneClicked = () => {
+                const newBranchName = prompt("Branch name: (ESC to cancel)", "branch");
+                if (newBranchName === null) {
+                    return;
+                }
+                if (globalState.some(([existingBranchName]) => existingBranchName === newBranchName)) {
+                    alert("Branch with this name already exists!");
+                    return;
+                }
+                const newModel = newVersionedModel({readonly: false, generateUUID, primitiveRegistry});
+                const newBranchState = newModel.initialState;
+
+                setGlobalState(prevGlobalState => [
+                    ...prevGlobalState.slice(0, i + 1),
+                    [newBranchName, newBranchState, newModel],
+                    ...prevGlobalState.slice(i + 1),
+                ]);
+
+                const setNewBranchState = getSetBranchState(i + 1);
+
+                const reducer = newModel.getReducer(setNewBranchState);
+                const compositeDeltas = [...getCurrentVersion()].reverse();
+                compositeDeltas.forEach((c: any) => {
+                    reducer.createAndGotoNewVersion(c.deltas, c.getDescription());
+                });
+            }
 
-        return <div key={branchName}>
-          <Divider my="sm" label={"branch: "+branchName} labelPosition="center" />
-            {/*{<CloseButton/>}*/}
-          <SimpleGrid cols={3}>
-            <div>
-              <Text>State</Text>
-              {components.graphStateComponent}
+            return <div key={branchName}>
+                <Divider my="sm" label={"branch: " + branchName} labelPosition="center"/>
+                {/*{<CloseButton/>}*/}
+                <SimpleGrid cols={3}>
+                    <div>
+                        <Text>State</Text>
+                        {components.graphStateComponent}
+                    </div>
+                    <div>
+                        <Text>History</Text>
+                        {components.historyComponent}
+                        <Space h="md"/>
+                        <SimpleGrid cols={4} spacing="xs">
+                            <Button onClick={unionClicked} compact disabled={i === 0}
+                                    leftIcon={<Icons.IconChevronUp/>}>Union </Button>
+                            {components.undoButton}
+                            {components.redoButton}
+                            <Button onClick={cloneClicked} compact rightIcon={<Icons.IconChevronDown/>}>Clone</Button>
+                        </SimpleGrid>
+                    </div>
+                    <div>
+                        <Text>Deltas (L0)</Text>
+                        {components.depGraphL0Component}
+                    </div>
+                </SimpleGrid>
+                <Space h="md"/>
             </div>
-            <div>
-              <Text>History</Text>
-              {components.historyComponent}
-              <Space h="md"/>
-              <SimpleGrid cols={4} spacing="xs">
-                <Button onClick={unionClicked} compact disabled={i===0} leftIcon={<Icons.IconChevronUp/>}>Union </Button>
-                {components.undoButton}
-                {components.redoButton}
-                <Button onClick={cloneClicked} compact rightIcon={<Icons.IconChevronDown/>}>Clone</Button>
-              </SimpleGrid>
-            </div>
-            <div>
-              <Text>Deltas (L0)</Text>
-              {components.depGraphL0Component}
-            </div>
-          </SimpleGrid>
-          <Space h="md"/>
-        </div>
-      })
-    }</>;
-  }
+        })
+        }</>;
+    }
 }

+ 2 - 1
src/frontend/versioned_model.tsx

@@ -55,7 +55,8 @@ const helpText = {
     <Mantine.Text>
       <b>Left-Drag</b>: Drag Node<br/>
       <b>Middle-Click</b>: Delete Node<br/>
-      <b>Right-Click</b>: Create Node or Edge<br/>
+      <b>Right-Click</b>: Create Node<br/>
+      <b>Right-Drag</b>: Create Edge (to Node or Value)<br/>
       <b>Wheel</b>: Zoom<br/>
     </Mantine.Text>
   </>,

+ 7 - 3
src/frontend/welcome.tsx

@@ -12,7 +12,7 @@ import {
     Card,
     CloseButton,
     Divider,
-    Space
+    Space, List
 } from "@mantine/core";
 
 import {PrimitiveRegistry} from "../onion/primitive_delta";
@@ -25,10 +25,14 @@ export const demo_Welcome_description =
             Welcome to our demonstrator!
         </Title>
         <Text>
-            First, we would like to show the basic possibilities of the graphical editor and then dive into the
-            different aspects of our new collaboration framework approach step by step.
+            This demo site performs two tasks:
         </Text>
+        <List type="ordered">
+            <List.Item>the possibilities of the approach are presented and</List.Item>
+            <List.Item>by the step-by-step structure, the understanding of our approach will be made easier.</List.Item>
+        </List>
         <Text>
+            In our explanations of the different views we use the following blocks:
             Every block with an <Text span c='darkorange'>orange</Text> mark on the left side contains an action
             that
             you should do. Each block with a <Text span c="royalblue">blue</Text> border describes what you can