Diese Präsentation wurde erfolgreich gemeldet.
Die SlideShare-Präsentation wird heruntergeladen. ×

openCPQ - A React-Based Product-Configuration Toolkit

openCPQ - A React-Based Product-Configuration Toolkit

Herunterladen, um offline zu lesen

The talk presents the new open-source project openCPQ for the web-based configuration of complex products. In contrast to popular commercial configuration tools openCPQ
- uses the browser not only for the UI but also for the business logic, which makes configurators extremely fast by avoiding round trips to the server,
- supports modelling of configuration rules embedded in JavaScript, which permits user-defined abstractions in a flexible way, and
- recomputes the configuration result from scratch instead of incrementally propagating changes in the user input, which fits nicely with React's architecture and makes openCPQ a light-weight framework.

Presented at the MunichJS meetup in May 2015 by Heribert Schütz and Tim Geisler

The talk presents the new open-source project openCPQ for the web-based configuration of complex products. In contrast to popular commercial configuration tools openCPQ
- uses the browser not only for the UI but also for the business logic, which makes configurators extremely fast by avoiding round trips to the server,
- supports modelling of configuration rules embedded in JavaScript, which permits user-defined abstractions in a flexible way, and
- recomputes the configuration result from scratch instead of incrementally propagating changes in the user input, which fits nicely with React's architecture and makes openCPQ a light-weight framework.

Presented at the MunichJS meetup in May 2015 by Heribert Schütz and Tim Geisler

Weitere Verwandte Inhalte

Ähnliche Bücher

Kostenlos mit einer 30-tägigen Testversion von Scribd

Alle anzeigen

Ähnliche Hörbücher

Kostenlos mit einer 30-tägigen Testversion von Scribd

Alle anzeigen

openCPQ - A React-Based Product-Configuration Toolkit

  1. 1. openCPQ – A React-Based Product-Configuration Toolkit Tim Geisler, Heribert Schütz webXcerpt Software GmbH tg@webxcerpt.com, hs@webxcerpt.com MunichJS Meetup, 2015-05-13
  2. 2. Product Configuration
  3. 3. Product Configuration Variants
  4. 4. Product Configuration Variants Parameters and Domains
  5. 5. Product Configuration Variants Parameters and Domains
  6. 6. Product Configuration Variants Parameters and Domains
  7. 7. Product Configuration Variants Parameters and Domains
  8. 8. Product Configuration , Dependencies Variants Parameters and Domains
  9. 9. Product Configuration , Dependencies Variants Parameters and Domains
  10. 10. Product Configuration , Dependencies Variants Parameters and Domains
  11. 11. Product Configuration , Dependencies Variants Parameters and Domains
  12. 12. Product Configuration , Dependencies Variants Parameters and Domains
  13. 13. Product Configuration , Dependencies Variants Parameters and Domains
  14. 14. Demo Optical Transport
  15. 15. Demo Example: Hierarchical Configuration SwitchRackSolution Board (Module) Transceiver (Wavelength)
  16. 16. Demo http://opencpq.webxcerpt.com/examples/optical-transport/ ^
  17. 17. Business Processes Configuration Engine User Configuration Which particular variant do I want to buy/sell?
  18. 18. Business Processes Configuration Engine User Configuration Which particular variant do I want to buy/sell? Manufacturing Plan Visualization Price(s) Bill of Materials ...
  19. 19. Business Processes Product Model Configuration Engine User Configuration Which variants of a product are available? Which particular variant do I want to buy/sell? Manufacturing Plan Visualization Price(s) Bill of Materials ...
  20. 20. Business Processes Modeling Tool Modeler Product Model Configuration Engine User Configuration Which variants of a product are available? Which particular variant do I want to buy/sell? Manufacturing Plan Visualization Price(s) Bill of Materials ...
  21. 21. Business Processes Modeling Tool Modeler Product Model Configuration Engine User Configuration Which variants of a product are available? Which particular variant do I want to buy/sell? Manufacturing Plan Visualization Price(s) Bill of Materials ... complex (web) applications
  22. 22. Business Processes Modeling Tool Modeler Product Model Configuration Engine User Configuration Which variants of a product are available? Which particular variant do I want to buy/sell? Manufacturing Plan Visualization Price(s) Bill of Materials ... complex (web) applications proprietary format
  23. 23. Problem 1
  24. 24. Product Model Modeling Tool Business Processes Modeler Configuration Engine User Configuration Which variants of a product are available? Which particular variant do I want to buy/sell? Manufacturing Plan Visualization Price(s) Bill of Materials ...
  25. 25. Business Processes Modeler Configuration Engine User Configuration Which variants of a product are available? Which particular variant do I want to buy/sell? Manufacturing Plan Visualization Price(s) Bill of Materials ... Customer-Specific Modeling Language Code Generator Product Model High-Level Product Model Customer-specific IDE
  26. 26. Business Processes Modeler Configuration Engine User Configuration Which variants of a product are available? Which particular variant do I want to buy/sell? Manufacturing Plan Visualization Price(s) Bill of Materials ... Customer-Specific Modeling Language Code Generator Product Model High-Level Product Model Customer-specific IDE ● Text ● Notions like „slot“, „board“, ...
  27. 27. Business Processes Modeler Configuration Engine User Configuration Which variants of a product are available? Which particular variant do I want to buy/sell? Manufacturing Plan Visualization Price(s) Bill of Materials ... Customer-Specific Modeling Language Code Generator Product Model High-Level Product Model Customer-specific IDE Based on ● Eclipse ● Xtext ● Text ● Notions like „slot“, „board“, ...
  28. 28. Product Models
  29. 29. Product Models ● Product parameters – Data types – Ranges
  30. 30. Product Models ● Product parameters – Data types – Ranges ● Components
  31. 31. Product Models ● Product parameters – Data types – Ranges ● Components ● Dependencies between parameters/components
  32. 32. Product Models ● Product parameters – Data types – Ranges ● Components ● Dependencies between parameters/components ● Calculation of additional output
  33. 33. Product Models ● Product parameters – Data types – Ranges ● Components ● Dependencies between parameters/components ● Calculation of additional output Models are programs!
  34. 34. Modeling as Programming
  35. 35. Modeling as Programming ● Abstractions, data structures
  36. 36. Modeling as Programming ● Abstractions, data structures ● Programming tools – Editors/IDEs – Debuggers and profilers – Revision control – Test and CI frameworks
  37. 37. Modeling as Programming ● Abstractions, data structures ● Programming tools – Editors/IDEs – Debuggers and profilers – Revision control – Test and CI frameworks ● General purpose tools and languages – Maturity – Re-usable knowledge, may already be available – Large communities and „ecosystems“
  38. 38. Problem 2
  39. 39. Configuring in the Browser
  40. 40. Configuring in the Browser Implement configurators in JavaScript.
  41. 41. Configuring in the Browser Implement configurators in JavaScript. JavaScript is also a reasonable choice for modeling.
  42. 42. Business Processes Modeling Tool Product Model Configuration Engine Manufacturing Plan Visualization Modeler User Configuration Which variants of a product are available? Which particular variant do I want to buy/sell? Price(s) Bill of Materials ...
  43. 43. Business Processes Manufacturing Plan Visualization Processes with openCPQ Editor / IDE Modeler JavaScript Code Browser User Configuration Which variants of a product are available? Which particular variant do I want to buy/sell? Price(s) Bill of Materials ... openCPQ
  44. 44. Business Processes Manufacturing Plan Visualization Processes with openCPQ Editor / IDE Modeler JavaScript Code Browser User Configuration Which variants of a product are available? Which particular variant do I want to buy/sell? Price(s) Bill of Materials ... openCPQ standard components
  45. 45. Business Processes Manufacturing Plan Visualization Processes with openCPQ Editor / IDE Modeler JavaScript Code Browser User Configuration Which variants of a product are available? Which particular variant do I want to buy/sell? Price(s) Bill of Materials ... openCPQ standard components expressive, popular
  46. 46. Business Processes Manufacturing Plan Visualization Processes with openCPQ Editor / IDE Modeler JavaScript Code Browser User Configuration Which variants of a product are available? Which particular variant do I want to buy/sell? Price(s) Bill of Materials ... openCPQ standard components light-weight layer expressive, popular
  47. 47. – a Configurator Toolkit in JS
  48. 48. ● Building-block library – Components – Dependencies – a Configurator Toolkit in JS
  49. 49. ● Building-block library – Components – Dependencies ● Combine building blocks with JavaScript – a Configurator Toolkit in JS
  50. 50. ● Building-block library – Components – Dependencies ● Combine building blocks with JavaScript ● Add application-specific building blocks – a Configurator Toolkit in JS
  51. 51. ● Building-block library – Components – Dependencies ● Combine building blocks with JavaScript ● Add application-specific building blocks ● A light-weight layer based on React and Bootstrap – a Configurator Toolkit in JS
  52. 52. – an Open-Source Project
  53. 53. Source code and links to live demos available on Github: https://github.com/webXcerpt/openCPQ – an Open-Source Project
  54. 54. Source code and links to live demos available on Github: https://github.com/webXcerpt/openCPQ Liberal MIT license – an Open-Source Project
  55. 55. Source code and links to live demos available on Github: https://github.com/webXcerpt/openCPQ Liberal MIT license Use, adapt, integrate, contribute! – an Open-Source Project
  56. 56. How it Works
  57. 57. Change Propagation: Non-Incremental core state
  58. 58. Change Propagation: Non-Incremental core state inference full state
  59. 59. Change Propagation: Non-Incremental core state user interfaceinference render full state
  60. 60. Change Propagation: Non-Incremental core state user interfaceinference render full state core state user update
  61. 61. Change Propagation: Non-Incremental core state user interfaceinference render full state core state user interface full state user update inference render
  62. 62. Change Propagation: Non-Incremental core state user interfaceinference render full state core state user interface full state core state user interface full state user update user update inference render inference render
  63. 63. Change Propagation: Incremental core state user interface full state user update core state user interface full state user update core state user interface full state
  64. 64. Change Propagation: Incremental core state user interface full state user update derived update core state user interface full state user update core state user interface full state
  65. 65. Change Propagation: Incremental core state user interface full state user update derived update derived update core state user interface full state user update core state user interface full state
  66. 66. Change Propagation: Incremental core state user interface full state user update derived update derived update core state user interface full state user update derived update derived update core state user interface full state
  67. 67. Change Propagation: Mixed core state user interface full state user update derived update core state user interface full state user update derived update core state user interface full state inference inference inference
  68. 68. React: A JavaScript library for building user interfaces
  69. 69. React: A JavaScript library for building user interfaces ● Unique approach: – not a widget library – not an MVC framework
  70. 70. React: A JavaScript library for building user interfaces ● Unique approach: – not a widget library – not an MVC framework ● Virtual DOM ("VDOM"): – Representation of the DOM tree as a JavaScript data structure (cheap!)
  71. 71. React: A JavaScript library for building user interfaces ● Unique approach: – not a widget library – not an MVC framework ● Virtual DOM ("VDOM"): – Representation of the DOM tree as a JavaScript data structure (cheap!) ● Upon each update:
  72. 72. React: A JavaScript library for building user interfaces ● Unique approach: – not a widget library – not an MVC framework ● Virtual DOM ("VDOM"): – Representation of the DOM tree as a JavaScript data structure (cheap!) ● Upon each update: – User code ● generates VDOM from your model ● possibly using XML templating integrated into JavaScript ("JSX")
  73. 73. React: A JavaScript library for building user interfaces ● Unique approach: – not a widget library – not an MVC framework ● Virtual DOM ("VDOM"): – Representation of the DOM tree as a JavaScript data structure (cheap!) ● Upon each update: – User code ● generates VDOM from your model ● possibly using XML templating integrated into JavaScript ("JSX") – React ● diffs the VDOM with the previous VDOM ● applies only the diff to the actual DOM
  74. 74. Architecture State (JSON)State (JSON) Nodes Nodes VDOM VDOM DOM Types render() apply delta Product Model Updates
  75. 75. Architecture State (JSON)State (JSON) Nodes Nodes VDOM VDOM DOM Types render() apply delta Product Model Updates
  76. 76. Architecture State (JSON)State (JSON) Nodes Nodes VDOM VDOM DOM Types render() apply delta Product Model Updates
  77. 77. Example Code: Product Model State (JSON)State (JSON) Nodes Nodes VDOM VDOM DOM Types render() apply delta Product Model Updates
  78. 78. Product Model: Cases with Details
  79. 79. Product Model: Cases with Details var configuration = CSelect([ unansweredCase("Select Configuration Mode"), ccase("Switches", "Optical Switches", CQuantifiedList({}, "Optical Switch", opticalSwitches)), ccase("Rack", "Racks", CQuantifiedList({}, "Rack", rack)), ccase("Solution", "Solution", solution), ]); cases details
  80. 80. Product Model: Cases with Details var configuration = CSelect([ unansweredCase("Select Configuration Mode"), ccase("Switches", "Optical Switches", CQuantifiedList({}, "Optical Switch", opticalSwitches)), ccase("Rack", "Racks", CQuantifiedList({}, "Rack", rack)), ccase("Solution", "Solution", solution), ]); cases details function configuration({caseId, details}) { switch (caseId) { case "unanswered": /* do nothing */ break; case "Switches": CQuantifiedList({}, "Optical Switch", opticalSwitches)(details); break; case "Rack": ...; break; case "Solution": solution(details); break; } } Compare to pseudocode:
  81. 81. Product Model: Cases with Details var configuration = CSelect([ unansweredCase("Select Configuration Mode"), ccase("Switches", "Optical Switches", CQuantifiedList({}, "Optical Switch", opticalSwitches)), ccase("Rack", "Racks", CQuantifiedList({}, "Rack", rack)), ccase("Solution", "Solution", solution), ]); cases details
  82. 82. Data-Driven Product Modeling
  83. 83. Data-Driven Product Modeling
  84. 84. Data-Driven Product Modeling
  85. 85. Data-Driven Product Modeling
  86. 86. Data-Driven Product Modeling function boards(isDoubleWidthSlot) { return CSelect([ for (b of components.boards) if (!b.doubleWidth || isDoubleWidthSlot) ccaseBOM(b.name, b.label, aggregate("power", b.power, ports(b.ports))) ]); }
  87. 87. Data-Driven Product Modeling function boards(isDoubleWidthSlot) { return CSelect([ for (b of components.boards) if (!b.doubleWidth || isDoubleWidthSlot) ccaseBOM(b.name, b.label, aggregate("power", b.power, ports(b.ports))) ]); } [for (… of …) if (…) …] array comprehension
  88. 88. Data-Driven Product Modeling function boards(isDoubleWidthSlot) { return CSelect([ for (b of components.boards) if (!b.doubleWidth || isDoubleWidthSlot) ccaseBOM(b.name, b.label, aggregate("power", b.power, ports(b.ports))) ]); } Concise specification of complex models
  89. 89. Example Data: State State (JSON)State (JSON) Nodes Nodes VDOM VDOM DOM Types render() apply delta Product Model Updates
  90. 90. Configuration State { "caseId": "Solution", "detailValue": { "project": { "release": { "caseId": "R2.0" }, "UPS": true }, "racks": [ { "quantity": "4", "value": { "UPS": true, "switches": [ … ] } } ] } }
  91. 91. Example Code: Node Rendering State (JSON)State (JSON) Nodes Nodes VDOM VDOM DOM Types render() apply delta Product Model Updates
  92. 92. Selection Node (simplified) class SelectNode extends Node { //constructor(options) { this.__options = options; } render() { var {cases, currentCase, detailNode, updateTo} = this.__options; return ( <div> <DropdownButton title={currentCase.label}> {[ for ({id, label} of cases) <MenuItem onSelect={() => updateTo({caseId: id})}> {label} </MenuItem> ]} </DropdownButton> {detailNode.render()} </div> ); } }
  93. 93. Selection Node (simplified) class SelectNode extends Node { //constructor(options) { this.__options = options; } render() { var {cases, currentCase, detailNode, updateTo} = this.__options; return ( <div> <DropdownButton title={currentCase.label}> {[ for ({id, label} of cases) <MenuItem onSelect={() => updateTo({caseId: id})}> {label} </MenuItem> ]} </DropdownButton> {detailNode.render()} </div> ); } } Inherited constructor Unpack constructor parameters.
  94. 94. Selection Node (simplified) class SelectNode extends Node { //constructor(options) { this.__options = options; } render() { var {cases, currentCase, detailNode, updateTo} = this.__options; return ( <div> <DropdownButton title={currentCase.label}> {[ for ({id, label} of cases) <MenuItem onSelect={() => updateTo({caseId: id})}> {label} </MenuItem> ]} </DropdownButton> {detailNode.render()} </div> ); } } Create a VDOM tree.
  95. 95. Selection Node (simplified) class SelectNode extends Node { //constructor(options) { this.__options = options; } render() { var {cases, currentCase, detailNode, updateTo} = this.__options; return ( <div> <DropdownButton title={currentCase.label}> {[ for ({id, label} of cases) <MenuItem onSelect={() => updateTo({caseId: id})}> {label} </MenuItem> ]} </DropdownButton> {detailNode.render()} </div> ); } } JSX: HTML templates in JavaScript
  96. 96. Selection Node (simplified) class SelectNode extends Node { //constructor(options) { this.__options = options; } render() { var {cases, currentCase, detailNode, updateTo} = this.__options; return ( <div> <DropdownButton title={currentCase.label}> {[ for ({id, label} of cases) <MenuItem onSelect={() => updateTo({caseId: id})}> {label} </MenuItem> ]} </DropdownButton> {detailNode.render()} </div> ); } } JSX: HTML templates in JavaScript … also with „higher-level“ XML elements (from react-bootstrap)
  97. 97. Selection Node (simplified) class SelectNode extends Node { //constructor(options) { this.__options = options; } render() { var {cases, currentCase, detailNode, updateTo} = this.__options; return ( <div> <DropdownButton title={currentCase.label}> {[ for ({id, label} of cases) <MenuItem onSelect={() => updateTo({caseId: id})}> {label} </MenuItem> ]} </DropdownButton> {detailNode.render()} </div> ); } } Interpolate JavaScript expressions with {...}
  98. 98. Selection Node (simplified) class SelectNode extends Node { //constructor(options) { this.__options = options; } render() { var {cases, currentCase, detailNode, updateTo} = this.__options; return ( <div> <DropdownButton title={currentCase.label}> {[ for ({id, label} of cases) <MenuItem onSelect={() => updateTo({caseId: id})}> {label} </MenuItem> ]} </DropdownButton> {detailNode.render()} </div> ); } } array comprehension
  99. 99. Selection Node (simplified) class SelectNode extends Node { //constructor(options) { this.__options = options; } render() { var {cases, currentCase, detailNode, updateTo} = this.__options; return ( <div> <DropdownButton title={currentCase.label}> {[ for ({id, label} of cases) <MenuItem onSelect={() => updateTo({caseId: id})}> {label} </MenuItem> ]} </DropdownButton> {detailNode.render()} </div> ); } }
  100. 100. Example Code: Types State (JSON)State (JSON) Nodes Nodes VDOM VDOM DOM Types render() apply delta Product Model Updates
  101. 101. function ccase(id, label, type = CUnit()) { return {id, label, type}; } function CSelect(cases) { return { makeNode(ctx) { var {state, updateTo} = ctx; var {caseId, detailState} = state || {caseId: cases[0].id}; var currentCase = cases.find(x => x.id === caseId); var detailNode = currentCase.type.makeNode({ ...ctx, state: detailState, updateTo(newDetail) { updateTo({caseId, detailState: newDetail}); } }); return new SelectNode({cases, currentCase, detailNode, updateTo}); } }; } Selection Type (simplified)
  102. 102. function ccase(id, label, type = CUnit()) { return {id, label, type}; } function CSelect(cases) { return { makeNode(ctx) { var {state, updateTo} = ctx; var {caseId, detailState} = state || {caseId: cases[0].id}; var currentCase = cases.find(x => x.id === caseId); var detailNode = currentCase.type.makeNode({ ...ctx, state: detailState, updateTo(newDetail) { updateTo({caseId, detailState: newDetail}); } }); return new SelectNode({cases, currentCase, detailNode, updateTo}); } }; } Selection Type (simplified)
  103. 103. function ccase(id, label, type = CUnit()) { return {id, label, type}; } function CSelect(cases) { return { makeNode(ctx) { var {state, updateTo} = ctx; var {caseId, detailState} = state || {caseId: cases[0].id}; var currentCase = cases.find(x => x.id === caseId); var detailNode = currentCase.type.makeNode({ ...ctx, state: detailState, updateTo(newDetail) { updateTo({caseId, detailState: newDetail}); } }); return new SelectNode({cases, currentCase, detailNode, updateTo}); } }; } Selection Type (simplified)
  104. 104. function ccase(id, label, type = CUnit()) { return {id, label, type}; } function CSelect(cases) { return { makeNode(ctx) { var {state, updateTo} = ctx; var {caseId, detailState} = state || {caseId: cases[0].id}; var currentCase = cases.find(x => x.id === caseId); var detailNode = currentCase.type.makeNode({ ...ctx, state: detailState, updateTo(newDetail) { updateTo({caseId, detailState: newDetail}); } }); return new SelectNode({cases, currentCase, detailNode, updateTo}); } }; } Selection Type (simplified) Nothing to configure
  105. 105. function ccase(id, label, type = CUnit()) { return {id, label, type}; } function CSelect(cases) { return { makeNode(ctx) { var {state, updateTo} = ctx; var {caseId, detailState} = state || {caseId: cases[0].id}; var currentCase = cases.find(x => x.id === caseId); var detailNode = currentCase.type.makeNode({ ...ctx, state: detailState, updateTo(newDetail) { updateTo({caseId, detailState: newDetail}); } }); return new SelectNode({cases, currentCase, detailNode, updateTo}); } }; } Selection Type (simplified)
  106. 106. function ccase(id, label, type = CUnit()) { return {id, label, type}; } function CSelect(cases) { return { makeNode(ctx) { var {state, updateTo} = ctx; var {caseId, detailState} = state || {caseId: cases[0].id}; var currentCase = cases.find(x => x.id === caseId); var detailNode = currentCase.type.makeNode({ ...ctx, state: detailState, updateTo(newDetail) { updateTo({caseId, detailState: newDetail}); } }); return new SelectNode({cases, currentCase, detailNode, updateTo}); } }; } Selection Type (simplified)
  107. 107. function ccase(id, label, type = CUnit()) { return {id, label, type}; } function CSelect(cases) { return { makeNode(ctx) { var {state, updateTo} = ctx; var {caseId, detailState} = state || {caseId: cases[0].id}; var currentCase = cases.find(x => x.id === caseId); var detailNode = currentCase.type.makeNode({ ...ctx, state: detailState, updateTo(newDetail) { updateTo({caseId, detailState: newDetail}); } }); return new SelectNode({cases, currentCase, detailNode, updateTo}); } }; } Selection Type (simplified)
  108. 108. function ccase(id, label, type = CUnit()) { return {id, label, type}; } function CSelect(cases) { return { makeNode(ctx) { var {state, updateTo} = ctx; var {caseId, detailState} = state || {caseId: cases[0].id}; var currentCase = cases.find(x => x.id === caseId); var detailNode = currentCase.type.makeNode({ ...ctx, state: detailState, updateTo(newDetail) { updateTo({caseId, detailState: newDetail}); } }); return new SelectNode({cases, currentCase, detailNode, updateTo}); } }; } Selection Type (simplified) Context: ● state ● updateTo() (replace state) ● aggregators (bill of materials, …) ● ... Injects application-specific data.
  109. 109. function ccase(id, label, type = CUnit()) { return {id, label, type}; } function CSelect(cases) { return { makeNode(ctx) { var {state, updateTo} = ctx; var {caseId, detailState} = state || {caseId: cases[0].id}; var currentCase = cases.find(x => x.id === caseId); var detailNode = currentCase.type.makeNode({ ...ctx, state: detailState, updateTo(newDetail) { updateTo({caseId, detailState: newDetail}); } }); return new SelectNode({cases, currentCase, detailNode, updateTo}); } }; } Selection Type (simplified) Context: ● state ● updateTo() (replace state) ● aggregators (bill of materials, …) ● ... Injects application-specific data.
  110. 110. function ccase(id, label, type = CUnit()) { return {id, label, type}; } function CSelect(cases) { return { makeNode(ctx) { var {state, updateTo} = ctx; var {caseId, detailState} = state || {caseId: cases[0].id}; var currentCase = cases.find(x => x.id === caseId); var detailNode = currentCase.type.makeNode({ ...ctx, state: detailState, updateTo(newDetail) { updateTo({caseId, detailState: newDetail}); } }); return new SelectNode({cases, currentCase, detailNode, updateTo}); } }; } Selection Type (simplified) detailNode = detailType(ctx')
  111. 111. function ccase(id, label, type = CUnit()) { return {id, label, type}; } function CSelect(cases) { return { makeNode(ctx) { var {state, updateTo} = ctx; var {caseId, detailState} = state || {caseId: cases[0].id}; var currentCase = cases.find(x => x.id === caseId); var detailNode = currentCase.type.makeNode({ ...ctx, state: detailState, updateTo(newDetail) { updateTo({caseId, detailState: newDetail}); } }); return new SelectNode({cases, currentCase, detailNode, updateTo}); } }; } Selection Type (simplified) detailNode = detailType(ctx') updateTo() for detail node: ● do not modify surrounding state ● send new state to parent's updateTo() => easy undo/redo
  112. 112. function ccase(id, label, type = CUnit()) { return {id, label, type}; } function CSelect(cases) { return { makeNode(ctx) { var {state, updateTo} = ctx; var {caseId, detailState} = state || {caseId: cases[0].id}; var currentCase = cases.find(x => x.id === caseId); var detailNode = currentCase.type.makeNode({ ...ctx, state: detailState, updateTo(newDetail) { updateTo({caseId, detailState: newDetail}); } }); return new SelectNode({cases, currentCase, detailNode, updateTo}); } }; } Selection Type (simplified)
  113. 113. function ccase(id, label, type = CUnit()) { return {id, label, type}; } function CSelect(cases) { return { makeNode(ctx) { var {state, updateTo} = ctx; var {caseId, detailState} = state || {caseId: cases[0].id}; var currentCase = cases.find(x => x.id === caseId); var detailNode = currentCase.type.makeNode({ ...ctx, state: detailState, updateTo(newDetail) { updateTo({caseId, detailState: newDetail}); } }); return new SelectNode({cases, currentCase, detailNode, updateTo}); } }; } Selection Type (simplified)
  114. 114. Tools
  115. 115. Tools ● react.js
  116. 116. Tools ● react.js ● bootstrap with ( or ?)
  117. 117. Tools ● react.js ● bootstrap with ( or ?) ● react-bootstrap, react-widgets
  118. 118. Tools ● react.js ● bootstrap with ( or ?) ● react-bootstrap, react-widgets ● ( react JSX/esprima; ?)
  119. 119. Tools ● react.js ● bootstrap with ( or ?) ● react-bootstrap, react-widgets ● ( react JSX/esprima; ?) ● webpack ( / )
  120. 120. Tools ● react.js ● bootstrap with ( or ?) ● react-bootstrap, react-widgets ● ( react JSX/esprima; ?) ● webpack ( / ) ● ( ),
  121. 121. Tools ● react.js ● bootstrap with ( or ?) ● react-bootstrap, react-widgets ● ( react JSX/esprima; ?) ● webpack ( / ) ● ( ), ●
  122. 122. Summary
  123. 123. Summary Take advantage of modern browser technology for product configuration.
  124. 124. Summary Take advantage of modern browser technology for product configuration. Powerful modeling based on JavaScript, React, and openCPQ.
  125. 125. Summary Take advantage of modern browser technology for product configuration. Powerful modeling based on JavaScript, React, and openCPQ. Flexible and fast user interface.
  126. 126. Summary Take advantage of modern browser technology for product configuration. Powerful modeling based on JavaScript, React, and openCPQ. Flexible and fast user interface. Use, adapt, integrate, contribute! https://github.com/webXcerpt/openCPQ
  127. 127. Issues to Discuss
  128. 128. Issues to Discuss ● Use cases – product configuration, software configuration – questionnaires – …?
  129. 129. Issues to Discuss ● Use cases – product configuration, software configuration – questionnaires – …? ● Technologies
  130. 130. Issues to Discuss ● Use cases – product configuration, software configuration – questionnaires – …? ● Technologies ● Cooperation – Extensions: Integrations (SAP, Salesforce, ...), Visualization, ... – Student projects – Application development

×