!7 concept Rule { S globalID = aGlobalIDUnlessLoading(); S text; S comments; // used by rule engine S notes; // for humans only toString { ret globalID + ": " + escapeNewLines(rtrim(text)); } void change { super.change(); vmBus_send('gazelleRuleChanged, this); } void delete { vmBus_send('gazelleRuleDeleted, this); super.delete(); } } // Bug when making cmodule module Rules > DynCRUD { transient CalculatedConceptFieldIndex byPurpose; enhanceFrame { internalFrameIcon(f, gazelle_frameIcon()); } start { dbIndexing(Rule, 'globalID); byPurpose = new CalculatedConceptFieldIndex(Rule, r -> gazelle_purposeFromComments(r.comments)); addCountToName(); crud.multiLineFields = litset('text, 'comments); crud.dontDuplicateFields = litset('globalID); crud.renderer = func(Rule r) -> Map { litorderedmap("Rule ID" := r.globalID, text := joinWithSpace(tlft(r.text)), comments := escapeNewLines(r.comments)) }; crud.latestFirst = true; onConceptsChange(r { vmBus_sendMessage('gazelleRulesChanged, this) }); conceptsObject().onAllChanged.add(r { vmBus_sendMessage('gazelleRulesGlobalChange, this) }); // do some logic stuff here for now dm_vmBus_onMessage_q('gazelleRuleCreated, voidfunc(O mod, O rule) { S ruleID = getString globalID(rule); print("wiring statement conditions for new rule: " + ruleID); dm_gazelle_wireStatementConditions(ruleID); }); } // API Pair addRule(S when, S then) { ret addRule(when + "\n=> " + then); } Pair addRule(S text) { ret addRuleWithComment(text, null); } Pair addRuleWithComment(S text, S comment) { Pair p = uniq2_sync(Rule, text := rtrim(text), comments := nullIfEmpty(rtrim(comment))); if (p.b) vmBus_sendMessage('gazelleRuleCreated, this, p.a); ret pair(p.a.globalID, p.b); } PairS textAndCommentForRule(S ruleID) { Rule r = conceptWhere Rule(globalID := ruleID); ret r == null ? null : pair(r.text, r.comments); } void setRuleText(S ruleID, S text) { cset(conceptWhere Rule(globalID := ruleID), +text); } void setComments(S ruleID, S comments) { cset(conceptWhere Rule(globalID := ruleID), +comments); } void addComments(S ruleID, S comments) { Rule r = conceptWhere Rule(globalID := ruleID); if (r != null) cset(r, comments := lines_rtrim(uniquifyList(concatLists(lines(r.comments), tlft(comments))))); } void removeComment(S ruleID, S comment) { Rule r = conceptWhere Rule(globalID := ruleID); if (r == null) ret; cset(r, comments := lines_rtrim(listWithout(lines(r.comments), comment))); } S latestRuleID() { ret getString globalID(last(concepts())); } void deleteRule(S ruleID) { deleteConceptsWhere Rule(globalID := ruleID); } void activateRule(S ruleID) { dm_activateOSAndModule(); // TODO: wait if (crud.table == null) ret; Rule r = conceptWhere Rule(globalID := ruleID); if (r == null) ret; selectRowIfNotNegative(crud.table, crud.indexOfConcept(r)); } // experimental L rulesForPurpose(S purpose) { ret byPurpose.getAll(purpose); } LS rulesWithText(S text) { ret collect globalID(conceptsWhere Rule(+text)); } }