Commit 4cab8231 authored by Tim Steenvoorden's avatar Tim Steenvoorden Committed by Steffen Michels

improve dynamic editor & add typed task editor example

parent 0131c660
Pipeline #31119 passed with stage
in 6 minutes and 34 seconds
/*
* CSS additions and fixes for typed task editor.
*/
/* Make labels occupy less space */
.itasks-label {
padding: 0em 1em 0em 0em;
width: auto;
}
/* Make containers have their natural sizes */
.itasks-container {
align-self: auto;
}
.typedtasks-evaluator {
align-self: unset;
}
/* Make generated labels flow on top */
.itasks-container.itasks-form-item {
flex-direction: column;
}
/* Set base padding and indent vertical structures horizontally */
.typedtasks-base {
flex: 0 0 auto;
padding: 0.2em 0.4em;
margin: 0.2em 1.6em;
}
/* Center horizontal structures vertically */
.typedtasks-horizontal {
flex-direction: row;
align-items: center;
}
.typedtasks-vertical {
flex-direction: column;
}
/* Add background boxes which get darker with nesting */
.typedtasks-boxed {
background-color: hsla(0,0%,0%,5%);
}
This diff is collapsed.
Version: 1.5
Global
ProjectRoot: .
Target: iTasks
Exec: {Project}/TypedTaskEditor
ByteCode: {Project}/TypedTaskEditor.bc
CodeGen
CheckStacks: False
CheckIndexes: True
OptimiseABC: True
GenerateByteCode: True
Application
HeapSize: 209715200
StackSize: 20971520
ExtraMemory: 8192
IntialHeapSize: 204800
HeapSizeMultiplier: 4096
ShowExecutionTime: False
ShowGC: False
ShowStackSize: False
MarkingCollector: False
DisableRTSFlags: False
StandardRuntimeEnv: True
Profile
Memory: False
MemoryMinimumHeapSize: 0
Time: False
Stack: False
Dynamics: True
GenericFusion: True
DescExL: True
Output
Output: ShowConstructors
Font: Monaco
FontSize: 9
WriteStdErr: False
Link
LinkMethod: Static
GenerateRelocations: False
GenerateSymbolTable: False
GenerateLinkMap: False
LinkResources: False
ResourceSource:
GenerateDLL: False
ExportedNames:
StripByteCode: True
KeepByteCodeSymbols: True
PrelinkByteCode: True
Paths
Path: {Project}
Precompile:
Postlink:
MainModule
Name: TypedTaskEditor
Dir: {Project}
Compiler
NeverMemoryProfile: False
NeverTimeProfile: False
StrictnessAnalysis: True
ListTypes: StrictExportTypes
ListAttributes: True
Warnings: True
Verbose: True
ReadableABC: False
ReuseUniqueNodes: True
Fusion: False
......@@ -13,7 +13,7 @@ from iTasks.WF.Tasks.Interaction import :: UpdateOption, updateInformation
from iTasks.WF.Combinators.Common import >>-
from iTasks.WF.Combinators.Overloaded import instance Functor Task, instance TMonad Task, class TMonad(..), class TApplicative, instance TApplicative Task
from iTasks.UI.Definition import :: Hint(..)
from iTasks.UI.Tune import class tune(..), @>>, instance tune Hint Task
from iTasks.UI.Tune import class tune(..), @>>, instance tune Hint (Task a)
from Data.Functor import class Functor
import StdString
......
......@@ -21,7 +21,7 @@ from iTasks.WF.Combinators.Common import -&&-, >>-
from iTasks.SDS.Sources.System import currentDateTime
from iTasks.Extensions.User import currentUser, :: User(..), :: UserTitle, :: Role, :: UserId, assign, workerAttributes, :: Password, :: Username, workAs, :: Credentials{..}, users
from iTasks.UI.Definition import :: Title(..), :: Hint(..)
from iTasks.UI.Tune import @>>, <<@, class tune, instance tune Hint Task, instance tune Title Task
from iTasks.UI.Tune import @>>, <<@, class tune, instance tune Hint (Task a), instance tune Title (Task a)
from iTasks.SDS.Definition import class RWShared(..)
from iTasks.WF.Tasks.Core import accWorld
import iTasks.Internal.Distributed.Symbols
......
.itasks-dynamic-editor-icon-error-container {
align-self: center;
padding: 0.2em;
}
.itasks-dynamic-editor-error {
background-color: #FFDDDD;
}
definition module iTasks.Extensions.Editors.DynamicEditor
import iTasks
/**
* This provides dynamic editors, which can be constructed dynamically by data
* and also can make use of the power of the dynamic type system which allows for quantified type variables.
* This makes it possible to achieve type safety similar to the safety provided by GADTs.
*
* The main idea is to provide a number of dynamic conses producing values and requiring arguments.
* For all required arguments the user has the choice between all dynamic conses providing a value of the proper type.
*/
:: DynamicEditor a =: DynamicEditor [DynamicEditorElement]
// phantom type only needed for top level
:: DynamicEditorValue a = DynamicEditorValue !DynamicConsId !DEVal | Undefined // TODO: Undefined can be removed once we have parametrised editors
from Data.Maybe import :: Maybe
from Data.GenEq import generic gEq
from Text.GenJSON import :: JSONNode, generic JSONEncode, generic JSONDecode
from iTasks import class iTask, class tune, generic gEditor, generic gText, :: Editor, :: TextFormat
/**
* This provides the iTasks editor corresponding to a dynamic editor definition.
*
* @param The dynamic editor definition.
* @result The iTasks editor.
*/
dynamicEditor :: !(DynamicEditor a) -> Editor (DynamicEditorValue a) | TC a
/**
* This provides the iTasks editor corresponding to a dynamic editor definition parametrised by an additional value.
* TODO: This could be done more clean if iTasks editor would support parameters.
*
* @param The parametrised dynamic editor definition.
* @result The iTasks editor additionally working on the parameter.
*/
parametrisedDynamicEditor ::
!(p -> DynamicEditor a) -> Editor (!p, !DynamicEditorValue a) | TC a & gEq{|*|}, JSONEncode{|*|}, JSONDecode{|*|} p
:: DEVal = DEApplication ![(!DynamicConsId, !DEVal)]
| DEJSONValue !JSONNode
/**
* Represents a dynamic editor value, which represents an actual value.
* There may however be multiple dynamic editor values mapping to the same actual value.
* Because of this only dynamic editor values can be edited by dynamic editors.
*/
:: DynamicEditorValue a
= DynamicEditorValue !DynamicConsId !DEVal
| Undefined // TODO: Undefined can be removed once we have parametrised editors
derive class iTask DynamicEditorValue
:: DynamicEditorElement = DynamicCons !DynamicCons | DynamicConsGroup !String ![DynamicCons]
/**
* The identity of a dynamic constructor.
*/
:: DynamicConsId :== String
/**
* The value of a dynamic editor constructor.
*/
:: DEVal = DEApplication ![(DynamicConsId, DEVal)] //* A dynamic constructor applied to a number of arguments.
| DEJSONValue !JSONNode //* An ordinary, JSON-encoded value.
/**
* `DynamicEditor a` provides a dynamic editor definition for editing values of type `a`.
*/
:: DynamicEditor a =: DynamicEditor [DynamicEditorElement]
/**
* valueCorrespondingTo dynamicEditor dynamicEditorValue = value:
* `value` is the actual value corresponding to `dynamicEditorValue` given `dynamicEditor`.
*/
valueCorrespondingTo :: !(DynamicEditor a) !(DynamicEditorValue a) -> a | TC a
/**
* stringRepresenting dynamicEditor dynamicEditorValue = string:
* `string` is the string representing `dynamicEditorValue` given `dynamicEditor`.
*/
stringCorrespondingTo :: !(DynamicEditor a) !(DynamicEditorValue a) -> String
/**
* Element of a dynamic editor definition.
*/
:: DynamicEditorElement
= DynamicCons !DynamicCons
//* Represents a dynamic construtor.
| DynamicConsGroup !String ![DynamicCons]
//* `DynamicConsGroup name conses` represents a group of `conses` with `name`.
//* Groups are used to structure the UI to make a large number of choices more accessible.
/**
* A dynamic constructor.
*/
:: DynamicCons
:: DynamicConsOption = HideIfOnlyChoice | UseAsDefault | ApplyCssClasses ![String]
(<<@@@) infixl 2 :: !DynamicCons !DynamicConsOption -> DynamicCons
(@@@>>) infixr 2 :: !DynamicConsOption !DynamicCons -> DynamicCons
/**
* functionCons id label function = dynamicCons:
* `dynamicCons` is the dynamic function constructor with identity `id` and `label`.
* The value of the element generated is the result value of `function`.
* For all arguments of `function` the user is given the possibility to enter a dynamic value
* of the corresponding types.
*/
functionCons :: !DynamicConsId !String !a -> DynamicCons | TC a
:: DynamicConsId :== String
:: DynamicConsBuilder = FunctionCons !Dynamic
| E.a: CustomEditorCons !(Editor a) & JSONEncode{|*|}, JSONDecode{|*|}, gText{|*|}, TC a
| ListCons !Dynamic //* must contain a value of type [a] -> b
/**
* A variant of `functionCons` using a `Dynamic` value as function.
* This variant is more powerful as dynamic values make it possible to use quantified type variables.
*/
functionConsDyn :: !DynamicConsId !String !Dynamic -> DynamicCons
functionCons :: !String !String !a -> DynamicCons | TC a
listCons :: !String !String !([a] -> b) -> DynamicCons | TC a & TC b
customEditorCons :: !String !String !(Editor a) -> DynamicCons | TC, JSONEncode{|*|}, JSONDecode{|*|}, gText{|*|} a
// dynamic variants are required because this is the only way to use quantified type variables
functionConsDyn :: !String !String !Dynamic -> DynamicCons
listConsDyn :: !String !String !Dynamic -> DynamicCons
/**
* listCons id label resultFor = dynamicCons:
* `dynamicCons` is the dynamic list constructor with identity `id` and `label`.
* The user is given the possibility to enter a `list` of dynamic value of type `a`.
* The editor's result is given by `resultFor list`.
*/
listCons :: !DynamicConsId !String !([a] -> b) -> DynamicCons | TC a & TC b
dynamicEditor :: !(DynamicEditor a) -> Editor (DynamicEditorValue a) | TC a
parametrisedDynamicEditor
:: !(p -> DynamicEditor a) -> Editor (!p, !DynamicEditorValue a)
| TC a & gEq{|*|}, JSONEncode{|*|}, JSONDecode{|*|} p
/**
* A variant of `listCons` using a `Dynamic` value as function.
* This variant is more powerful as dynamic values make it possible to use quantified type variables.
* The dynamic argument must be of type `[a] -> b`, which cannot be enforced by the type system!
*/
listConsDyn :: !DynamicConsId !String !Dynamic -> DynamicCons
/**
* customEditorCons id label editor = dynamicCons:
* `dynamicCons` is the dynamic constructor with identity `id` and `label` corresponding to the iTasks `editor`.
*/
customEditorCons ::
!DynamicConsId !String !(Editor a) -> DynamicCons | TC, JSONEncode{|*|}, JSONDecode{|*|}, gText{|*|} a
instance tune DynamicConsOption DynamicCons
toValue :: !(DynamicEditor a) !(DynamicEditorValue a) -> a | TC a
dynEditorValToString :: !(DynamicEditor a) !(DynamicEditorValue a) -> String
/**
* Options to tune dynamic conses.
*/
:: DynamicConsOption
= HideIfOnlyChoice //* Hide the choice for this cons, if there are no other applicable conses.
| UseAsDefault //* As this cons as default, i.e. the cons is pre-selected in the UI.
| ApplyCssClasses ![String] //* CSS classes applied to the UI if the cons is selected.
| AddLabels ![Maybe String]
//* Labels for the cons arguments, if the list contains too many labels the rest of ignored.
......@@ -10,7 +10,7 @@ from iTasks.Internal.Generic.Visualization import :: TextFormat(..)
from Data.Maybe import :: Maybe
from Data.Map import :: Map, newMap
from iTasks.UI.Editor.Modifiers import comapEditorValue, instance tune UIAttributes Editor
from iTasks.UI.Editor.Modifiers import comapEditorValue, instance tune UIAttributes (Editor a)
from iTasks.UI.Editor.Controls import htmlView
from iTasks.UI.Definition import :: UIAttributes
from Text.HTML import :: HtmlTag(ImgTag), :: HtmlAttr(SrcAttr,StyleAttr,AltAttr)
......
......@@ -286,7 +286,7 @@
padding: 8px 10px;
font-size: 12px;
line-height: 12px;
white-space: nowrap;
white-space: pre;
box-shadow: 4px 4px 8px rgba(0, 0, 0, 0.3);
}
*.itasks-viewport [data-tooltip]:before {
......
......@@ -86,34 +86,34 @@ insertToolBar :: [String] -> LayoutRule
//Convenient annotatation types
:: ArrangeWithTabs = ArrangeWithTabs Bool
instance tune ArrangeWithTabs Task
instance tune ArrangeWithTabs (Task a)
:: ArrangeWithSideBar = ArrangeWithSideBar !Int !UISide !Bool
instance tune ArrangeWithSideBar Task
instance tune ArrangeWithSideBar (Task a)
:: ArrangeWithHeader = ArrangeWithHeader !Int
instance tune ArrangeWithHeader Task
instance tune ArrangeWithHeader (Task a)
:: ArrangeAsMenu = ArrangeAsMenu [[Int]]
instance tune ArrangeAsMenu Task
instance tune ArrangeAsMenu (Task a)
:: ArrangeSplit = ArrangeSplit !UIDirection !Bool
instance tune ArrangeSplit Task
instance tune ArrangeSplit (Task a)
:: ArrangeVertical = ArrangeVertical
instance tune ArrangeVertical Task
instance tune ArrangeVertical (Task a)
:: ArrangeHorizontal = ArrangeHorizontal
instance tune ArrangeHorizontal Task
instance tune ArrangeHorizontal (Task a)
:: ScrollContent = ScrollContent
instance tune ScrollContent Task
instance tune ScrollContent (Task a)
:: AddCSSClass = AddCSSClass !String
instance tune AddCSSClass Task
instance tune AddCSSClass (Task a)
:: CSSStyle = CSSStyle !String
instance tune CSSStyle Task
instance tune CSSStyle (Task a)
//Changing container types
......@@ -126,16 +126,16 @@ toEmpty :: LayoutRule
InWindow :== InFloatingWindow
InFloatingWindow :== ToWindow FloatingWindow AlignMiddle AlignCenter
InNotificationBubble :== ToWindow NotificationBubble AlignTop AlignRight
instance tune ToWindow Task
instance tune ToWindow (Task a)
:: InPanel = InPanel Bool //Indicate that a task should be wrapped in a panel
instance tune InPanel Task
instance tune InPanel (Task a)
:: InContainer = InContainer //Indicate that a task should be wrapped in a panel
instance tune InContainer Task
instance tune InContainer (Task a)
:: NoUserInterface = NoUserInterface //Replace the UI by an empty UI
instance tune NoUserInterface Task
instance tune NoUserInterface (Task a)
actionToButton :: LayoutRule
......
......@@ -279,58 +279,58 @@ where
>>= \(JSONString f) -> 'DM'.get f icons
>>= \icon -> return ('DM'.union (iconClsAttr ("icon-" +++ icon)) attr)
instance tune ArrangeWithTabs Task
instance tune ArrangeWithTabs (Task a)
where tune (ArrangeWithTabs b) t = tune (ApplyLayout (arrangeWithTabs b)) t
instance tune ArrangeWithSideBar Task
instance tune ArrangeWithSideBar (Task a)
where
tune (ArrangeWithSideBar index side resize) t = tune (ApplyLayout (arrangeWithSideBar index side resize)) t
instance tune ArrangeWithHeader Task
instance tune ArrangeWithHeader (Task a)
where
tune (ArrangeWithHeader index) t = tune (ApplyLayout (arrangeWithHeader index)) t
instance tune ArrangeAsMenu Task
instance tune ArrangeAsMenu (Task a)
where
tune (ArrangeAsMenu i) t = tune (ApplyLayout (arrangeAsMenu i)) t
instance tune ArrangeSplit Task
instance tune ArrangeSplit (Task a)
where
tune (ArrangeSplit direction resize) t = tune (ApplyLayout (arrangeSplit direction resize)) t
instance tune ArrangeVertical Task
instance tune ArrangeVertical (Task a)
where
tune ArrangeVertical t = tune (ApplyLayout arrangeVertical) t
instance tune ArrangeHorizontal Task
instance tune ArrangeHorizontal (Task a)
where
tune ArrangeHorizontal t = tune (ApplyLayout arrangeHorizontal) t
instance tune ScrollContent Task
instance tune ScrollContent (Task a)
where
tune ScrollContent t = tune (ApplyLayout scrollContent) t
instance tune AddCSSClass Task
instance tune AddCSSClass (Task a)
where
tune (AddCSSClass s) t = tune (ApplyLayout (addCSSClass s)) t
instance tune CSSStyle Task
instance tune CSSStyle (Task a)
where
tune (CSSStyle s) t = tune ("style",JSONString s) t
instance tune ToWindow Task
instance tune ToWindow (Task a)
where
tune (ToWindow windowType vpos hpos) t = tune (ApplyLayout (toWindow windowType vpos hpos)) t
instance tune InPanel Task
instance tune InPanel (Task a)
where
tune (InPanel fullscreenable) t = tune (ApplyLayout (toPanel fullscreenable)) t
instance tune InContainer Task
instance tune InContainer (Task a)
where
tune InContainer t = tune (ApplyLayout toContainer) t
instance tune NoUserInterface Task
instance tune NoUserInterface (Task a)
where
tune NoUserInterface task = Task (eval task)
where
......
......@@ -13,34 +13,31 @@ from iTasks.WF.Definition import :: Task
* Fine tune a task or editor by specifying custom layouts, tweaking generic layouts,
* or adding additional titles, hints and descriptions
*/
class tune b f :: !b !(f a) -> f a
class tunev b a f | iTask a :: !(b a) !(f a) -> f a
class tune option tunedItem :: !option !tunedItem -> tunedItem
/**
* Infix shorthands for the (overloaded) tune combinator.
*/
(<<@) infixl 2 :: !(f a) !b -> f a | tune b f
(@>>) infixr 2 :: !b !(f a) -> f a | tune b f
(<@@) infixl 2 :: !(f a) !(b a) -> f a | tunev b a f & iTask a
(@@>) infixr 2 :: !(b a) !(f a) -> f a | tunev b a f & iTask a
(<<@) infixl 2 :: !tunedItem !option -> tunedItem | tune option tunedItem
(@>>) infixr 2 :: !option !tunedItem -> tunedItem | tune option tunedItem
//* Overwriting attributes with constants
instance tune UIAttribute Task
instance tune UIAttributes Task
instance tune UIAttribute Editor
instance tune UIAttributes Editor
instance tune UIAttribute (Task a)
instance tune UIAttributes (Task a)
instance tune UIAttribute (Editor a)
instance tune UIAttributes (Editor a)
//* Common attributes
instance tune Title Task
instance tune Hint Task
instance tune Label Task
instance tune Icon Task
instance tune Title Editor
instance tune Hint Editor
instance tune Label Editor
instance tune Icon Editor
instance tune Title (Task a)
instance tune Hint (Task a)
instance tune Label (Task a)
instance tune Icon (Task a)
instance tune Title (Editor a)
instance tune Hint (Editor a)
instance tune Label (Editor a)
instance tune Icon (Editor a)
//* Apply a layout transform to a task
:: ApplyLayout = ApplyLayout LayoutRule
instance tune ApplyLayout Task
:: ApplyLayout = ApplyLayout !LayoutRule
instance tune ApplyLayout (Task a)
......@@ -13,38 +13,29 @@ import qualified Data.Set as DS
import qualified Data.Map as DM
import qualified iTasks.Internal.SDS as SDS
class tune b f :: !b !(f a) -> f a
class tunev b a f | iTask a :: !(b a) !(f a) -> f a
(<<@) infixl 2 :: !(f a) !b -> f a | tune b f
(<<@) infixl 2 :: !tunedItem !option -> tunedItem | tune option tunedItem
(<<@) t a = tune a t
(@>>) infixr 2 :: !b !(f a) -> f a | tune b f
(@>>) infixr 2 :: !option !tunedItem -> tunedItem | tune option tunedItem
(@>>) a t = tune a t
(<@@) infixl 2 :: !(f a) !(b a) -> f a | tunev b a f & iTask a
(<@@) t a = tunev a t
(@@>) infixr 2 :: !(b a) !(f a) -> f a | tunev b a f & iTask a
(@@>) a t = tunev a t
instance tune UIAttribute Editor
instance tune UIAttribute (Editor a)
where
tune (k,v) editor=:{Editor|genUI=editorGenUI} = {Editor|editor & genUI = genUI}
where
genUI attr dp mode vst = editorGenUI ('DM'.put k v attr) dp (mapEditMode id mode) vst
instance tune UIAttributes Editor
instance tune UIAttributes (Editor a)
where
tune extra editor=:{Editor|genUI=editorGenUI} = {Editor|editor & genUI = genUI}
where
genUI attr dp mode vst = editorGenUI ('DM'.union extra attr) dp (mapEditMode id mode) vst
instance tune UIAttribute Task
instance tune UIAttribute (Task a)
where
tune attr task = tune ('DM'.fromList [attr]) task
instance tune UIAttributes Task
instance tune UIAttributes (Task a)
where
tune attrs task = Task (eval task)
where
......@@ -65,27 +56,27 @@ where
withExtraAttributes extra result = result
instance tune Title Task
instance tune Title (Task a)
where tune (Title title) t = tune (titleAttr title) t
instance tune Title Editor
instance tune Title (Editor a)
where tune (Title title) e = tune (titleAttr title) e
instance tune Hint Task
instance tune Hint (Task a)
where tune (Hint hint) t = tune (hintAttr hint) t
instance tune Hint Editor
instance tune Hint (Editor a)
where tune (Hint hint) e = tune (hintAttr hint) e
instance tune Icon Task
instance tune Icon (Task a)
where tune (Icon icon) t = tune ('DM'.fromList [(ICON_ATTRIBUTE,JSONString icon)]) t
instance tune Icon Editor
instance tune Icon (Editor a)
where tune (Icon icon) e = tune ('DM'.fromList [(ICON_ATTRIBUTE,JSONString icon)]) e
instance tune Label Task
instance tune Label (Task a)
where tune (Label label) t = tune ('DM'.fromList [(LABEL_ATTRIBUTE,JSONString label)]) t
instance tune Label Editor
instance tune Label (Editor a)
where tune (Label label) e = tune ('DM'.fromList [(LABEL_ATTRIBUTE,JSONString label)]) e
instance tune ApplyLayout Task
instance tune ApplyLayout (Task a)
where tune (ApplyLayout l) task = applyLayout l task
applyLayout :: LayoutRule (Task a) -> Task a
......
......@@ -141,9 +141,9 @@ itasks.NumberField = {
width: 150
},
initDOMEl: function() {
var me = this,
el = this.domEl;
el.type = 'text';
var me = this,
el = this.domEl;
el.type = 'number';
el.value = (me.attributes.value === undefined || me.attributes.value === null) ? '' : me.attributes.value;
if('enabled' in me.attributes && me.attributes['enabled'] === false) {
......
......@@ -279,11 +279,23 @@ itasks.Component = {
setAttribute: function(name,value) {
var me = this;
me.attributes[name] = value;
me.attributes[name] = value;
me.onAttributeChange(name,value);
},
onAttributeChange: function(name,value) {},
onAttributeChange: function(name,value) {
var me = this;
if(name == 'class') {
me.domEl.className = '';
if(Array.isArray(value)) {
value.forEach(function(cls) {
me.domEl.classList.add(cls);
});
} else {
me.domEl.classList.add(value);
}
}
},
onUIChange: function(change) {
var me = this;
me.world=me.world.then (function(){
......
......@@ -148,7 +148,7 @@ editSelection` attributes (SelectUsing toView fromView editor) container sel
{onInit = \r -> (Update (toView container,sel))
,onEdit = \_ -> Nothing
,onRefresh = \_ v -> (v,Nothing)
} (attributes @>> editor) @ (\(_,(_,sel)) -> fromView container sel)
} (withAttributes attributes editor) @ (\(_,(_,sel)) -> fromView container sel)
editSelectionWithShared :: ![SelectOption c a] (sds () c w) (c -> [Int]) -> Task [a] | iTask c & iTask a & TC w & RWShared sds
editSelectionWithShared options sharedContainer initSel = editSelectionWithShared` (selectAttributes options) (selectEditor options) sharedContainer initSel
......@@ -157,7 +157,7 @@ editSelectionWithShared` attributes (SelectUsing toView fromView editor) sharedC
{onInit = \r -> Update (toView r, initSel r)
,onEdit = \_ -> Nothing
,onRefresh = \r v -> ((\(_, sel) -> (toView r,sel)) <$> v,Nothing)
} (attributes @>> editor) @ (\(container,(_,sel)) -> fromView container sel)
} (withAttributes attributes editor) @ (\(container,(_,sel)) -> fromView container sel)
editSharedSelection :: ![SelectOption c a] c (Shared sds [Int]) -> Task [a] | iTask c & iTask a & RWShared sds
editSharedSelection options container sharedSel = editSharedSelection` (selectAttributes options) (selectEditor options) container sharedSel
......@@ -166,7 +166,7 @@ editSharedSelection` attributes (SelectUsing toView fromView editor) container s
{onInit = \r -> Update (toView container,r)
,onEdit = \(_,vs) -> Just (const vs)
,onRefresh = \r v -> ((\(vt, _) -> (vt, r)) <$> v,Nothing)
} (attributes @>> editor) @ (\(_,(_,sel)) -> fromView container sel)
} (withAttributes attributes editor) @ (\(_,(_,sel)) -> fromView container sel)
editSharedSelectionWithShared :: ![SelectOption c a] (sds1 () c w) (Shared sds2 [Int]) -> Task [a] | iTask c & iTask a & TC w & RWShared sds1 & RWShared sds2
editSharedSelectionWithShared options sharedContainer sharedSel
......@@ -176,7 +176,7 @@ editSharedSelectionWithShared` attributes (SelectUsing toView fromView editor) s
{onInit = \(rc, rs) -> Update (toView rc,rs)
,onEdit = \(_, vs) -> Just (const vs)
,onRefresh = \(rc, rs) _ -> (Just (toView rc, rs), Nothing)
} (attributes @>> editor) @ (\((container,_),(_,sel)) -> fromView container sel)
} (withAttributes attributes editor) @ (\((container,_),(_,sel)) -> fromView container sel)
//Core choice tasks
editChoice :: ![ChoiceOption a] ![a] (Maybe a) -> Task a | iTask a
......@@ -365,3 +365,7 @@ crud :: !((f r) -> [r]) !(r (f r) -> f` w) !(r (f r) -> f` w)
(sds () (f r) (f` w))
-> Task r | iTask r & iTask (f r) & iTask w & iTask (f` w) & RWShared sds
crud toList putItem delItem sh = crudWith [] [] [] [] toList putItem delItem sh
// required to solve overloading
withAttributes :: !UIAttributes !(Editor a) -> Editor a
withAttributes attributes editor = attributes @>> editor
Markdown is supported
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