<commit_before>/// <reference path="uiEditor.ts" />
/// <reference path="tableEditor.ts" />
/// <reference path="microReact.ts" />
/// <reference path="uiEditorRenderer.ts" />
/// <reference path="indexer.ts" />
/// <reference path="client.ts" />
/// <reference path="eveEditor.ts" />
/// <reference path="api.ts" />
module queryEditor {
  declare var uuid;
  declare var queryEditor;
  declare var DEBUG;

  var document = window.document;
  var ixer = api.ixer;
  var code = api.code;
  var diff = api.diff;
  var localState = api.localState;
  var clone = api.clone;
  var alphabet = api.alphabet;
  var KEYS = api.KEYS;

  if(window["queryEditor"]) {
    try {
      document.body.removeChild(window["queryEditor"].container);
    } catch (err) {
      // meh
    }
  }
  
  function focusOnce(node, elem) {
    if(!elem.__focused) {
      setTimeout(function() { node.focus(); }, 5);
      elem.__focused = true;
    }
  }

  //---------------------------------------------------------
  // utils
  //---------------------------------------------------------

  
  function coerceInput(input) {
    if(input.match(/^-?[\d]+$/gim)) {
      return parseInt(input);
    } else if(input.match(/^-?[\d]+\.[\d]+$/gim)) {
      return parseFloat(input);
    } else if(input === "true") {
      return true;
    } else if(input === "false") {
      return false;
    }
    return input;
  }
  
  function stopPropagation(e) {
    e.stopPropagation();
  }
  function preventDefault(e) {
    e.preventDefault();
  }


  //---------------------------------------------------------
  // Dispatch
  //---------------------------------------------------------

  export function dispatch(evt: string, info: any) {
    //         console.info("[dispatch]", evt, info);
    var storeEvent = true;
    var sendToServer = true;
    var txId = ++localState.txId;
  	var redispatched = false;
    var diffs:api.Diff = [];
    switch(evt) {
      case "exportView":
        var changes = [api.remove("query export", {query: info.queryId}),
                       api.insert("query export", {query: info.queryId, view: info.viewId})];
        diffs = api.toDiffs(changes);
        break;
      case "addViewBlock":
        var queryId = (info.queryId !== undefined) ? info.queryId: code.activeItemId();
        var name = api.getUniqueName(code.queryViews(queryId), api.alphabet);
        
        diffs = api.toDiffs(api.insert("view", {
          view: info.viewId,
          kind: info.kind,
          dependents: {
            "display name": {name: name},
            tag: [{tag: "local"}, {tag: "remote"}],
            block: {query: queryId},
            source: (info.sourceId ? {
              "source view": api.diff2.source(info.sourceId)
            } : undefined)
          }
        }));                                                             
        break;
      case "addAggregateBlock":
        var queryId = (info.queryId !== undefined) ? info.queryId: code.activeItemId();
        var name = api.getUniqueName(code.queryViews(queryId), api.alphabet);
        
        diffs = api.toDiffs(api.insert("view", {
          view: info.viewId,
          kind: "aggregate",
          dependents: {
            "display name": {name: name},
            tag: [{tag: "local"}, {tag: "remote"}],
            block: {query: queryId},
            "block aggregate": {kind: info.kind},
            source: [
              {source: "inner", "source view": "empty view"},
              {source: "outer", "source view": "empty view"},
              api.diff2.source(info.kind)
            ]
          }
        }));
        break;
      case "removeViewBlock":
        diffs = api.toDiffs(api.remove("view", {view: info.viewId}));
        break;
      case "addViewSelection":
        var neueField;
        if(!info.fieldId || !ixer.selectOne("field", {view: info.viewId, field: info.fieldId})) {
          var name = code.name(info.sourceFieldId);
          var calculated = ixer.selectOne("calculated field", {view: info.viewId, source: info.sourceId, field: info.sourceFieldId});
          if(calculated) {
            name = code.name(calculated["calculated field: calculated field"]);
          }

          var fields = ixer.selectPretty("field", {view: info.viewId}) || [];
          neueField = api.insert("field", {view: info.viewId, field: info.fieldId, kind: "output", dependents: {
            "display name": {name: name},
            "display order": {priority: -fields.length}
          }});
          info.fieldId = neueField.content.field;
          console.log("neue", info.fieldId);
        }
      
        diffs = api.toDiffs([
          neueField,
          api.remove("select", {view: info.viewId, "view field": info.fieldId, source: (info.isUnion ? info.sourceId : undefined)}),
          api.insert("select", {view: info.viewId, "view field": info.fieldId, source: info.sourceId, "source field": info.sourceFieldId})
        ]);

        if(info.isUnion) {
          var sources = ixer.select("source", {view: info.viewId}) || [];
          var numSources = sources.reduce(function(memo, source) {
            return (source["source: source"] !== info.sourceId) ? memo + 1 : memo;
          }, 1);
          var fields = ixer.select("field", {view: info.viewId}) || [];
          var numFields = fields.reduce(function(memo, field) {
            return (field["field: field"] !== info.fieldId) ? memo + 1 : memo;
          }, 1);
          var selects = ixer.select("select", {view: info.viewId}) || [];
          var numSelects = selects.reduce(function(memo, select) {
            return (select["select: source"] !== info.sourceId || select["select: view field"] !== info.fieldId) ? memo + 1 : memo;
          }, 1);
          
          console.log(numSelects, "=", numFields, "*", numSources);
          
          if(numSelects !== numFields * numSources) {
            sendToServer = false;
          } else {
            diffs = diffs.concat(api.toDiffs({type: "view", content: api.retrieve("view", {view: info.viewId}), mode: "inserted"}));
          }
        }
        break;
      case "addViewSource":
        var neueSource = api.insert("source", api.diff2.source(info.sourceId, info.kind), {view: info.viewId});
        var autoJoinConstraints = api.diff2.autojoin(info.viewId, neueSource.content["source"], info.sourceId);
        
        var viewKind = (api.ixer.selectOne("view", {view: info.viewId}) || {})["view: kind"];
        if(viewKind === "union") {
          let selects = ixer.select("select", {view: info.viewId});
          if(selects.length) {
            sendToServer = false;
          }
        }
        diffs = api.toDiffs([neueSource].concat(autoJoinConstraints));
        break;
      case "removeViewSource":
        diffs = api.toDiffs(api.remove("source", {view: info.viewId, source: info.sourceId}));
        break;
      case "addViewConstraint":
      var rightSource = info.rightSource || info.leftSource;
      var rightField = info.rightField || info.leftField;
      diffs = api.toDiffs(api.insert("constraint", {
        view: info.viewId,
        operation: "=",
        "left source": info.leftSource,
        "left field": info.leftField,
        "right source": rightSource,
        "right field": rightField
      }));
      sendToServer = info.leftSource && info.leftField && info.rightSource && info.rightField;<commit_msg>Fix failure to remove sources when replacing in addViewSource<commit_after>/// <reference path="uiEditor.ts" />
/// <reference path="tableEditor.ts" />
/// <reference path="microReact.ts" />
/// <reference path="uiEditorRenderer.ts" />
/// <reference path="indexer.ts" />
/// <reference path="client.ts" />
/// <reference path="eveEditor.ts" />
/// <reference path="api.ts" />
module queryEditor {
  declare var uuid;
  declare var queryEditor;
  declare var DEBUG;

  var document = window.document;
  var ixer = api.ixer;
  var code = api.code;
  var diff = api.diff;
  var localState = api.localState;
  var clone = api.clone;
  var alphabet = api.alphabet;
  var KEYS = api.KEYS;

  if(window["queryEditor"]) {
    try {
      document.body.removeChild(window["queryEditor"].container);
    } catch (err) {
      // meh
    }
  }
  
  function focusOnce(node, elem) {
    if(!elem.__focused) {
      setTimeout(function() { node.focus(); }, 5);
      elem.__focused = true;
    }
  }

  //---------------------------------------------------------
  // utils
  //---------------------------------------------------------

  
  function coerceInput(input) {
    if(input.match(/^-?[\d]+$/gim)) {
      return parseInt(input);
    } else if(input.match(/^-?[\d]+\.[\d]+$/gim)) {
      return parseFloat(input);
    } else if(input === "true") {
      return true;
    } else if(input === "false") {
      return false;
    }
    return input;
  }
  
  function stopPropagation(e) {
    e.stopPropagation();
  }
  function preventDefault(e) {
    e.preventDefault();
  }


  //---------------------------------------------------------
  // Dispatch
  //---------------------------------------------------------

  export function dispatch(evt: string, info: any) {
    //         console.info("[dispatch]", evt, info);
    var storeEvent = true;
    var sendToServer = true;
    var txId = ++localState.txId;
  	var redispatched = false;
    var diffs:api.Diff = [];
    switch(evt) {
      case "exportView":
        var changes = [api.remove("query export", {query: info.queryId}),
                       api.insert("query export", {query: info.queryId, view: info.viewId})];
        diffs = api.toDiffs(changes);
        break;
      case "addViewBlock":
        var queryId = (info.queryId !== undefined) ? info.queryId: code.activeItemId();
        var name = api.getUniqueName(code.queryViews(queryId), api.alphabet);
        
        diffs = api.toDiffs(api.insert("view", {
          view: info.viewId,
          kind: info.kind,
          dependents: {
            "display name": {name: name},
            tag: [{tag: "local"}, {tag: "remote"}],
            block: {query: queryId},
            source: (info.sourceId ? {
              "source view": api.diff2.source(info.sourceId)
            } : undefined)
          }
        }));                                                             
        break;
      case "addAggregateBlock":
        var queryId = (info.queryId !== undefined) ? info.queryId: code.activeItemId();
        var name = api.getUniqueName(code.queryViews(queryId), api.alphabet);
        
        diffs = api.toDiffs(api.insert("view", {
          view: info.viewId,
          kind: "aggregate",
          dependents: {
            "display name": {name: name},
            tag: [{tag: "local"}, {tag: "remote"}],
            block: {query: queryId},
            "block aggregate": {kind: info.kind},
            source: [
              {source: "inner", "source view": "empty view"},
              {source: "outer", "source view": "empty view"},
              api.diff2.source(info.kind)
            ]
          }
        }));
        break;
      case "removeViewBlock":
        diffs = api.toDiffs(api.remove("view", {view: info.viewId}));
        break;
      case "addViewSelection":
        var neueField;
        if(!info.fieldId || !ixer.selectOne("field", {view: info.viewId, field: info.fieldId})) {
          var name = code.name(info.sourceFieldId);
          var calculated = ixer.selectOne("calculated field", {view: info.viewId, source: info.sourceId, field: info.sourceFieldId});
          if(calculated) {
            name = code.name(calculated["calculated field: calculated field"]);
          }

          var fields = ixer.selectPretty("field", {view: info.viewId}) || [];
          neueField = api.insert("field", {view: info.viewId, field: info.fieldId, kind: "output", dependents: {
            "display name": {name: name},
            "display order": {priority: -fields.length}
          }});
          info.fieldId = neueField.content.field;
          console.log("neue", info.fieldId);
        }
      
        diffs = api.toDiffs([
          neueField,
          api.remove("select", {view: info.viewId, "view field": info.fieldId, source: (info.isUnion ? info.sourceId : undefined)}),
          api.insert("select", {view: info.viewId, "view field": info.fieldId, source: info.sourceId, "source field": info.sourceFieldId})
        ]);

        if(info.isUnion) {
          var sources = ixer.select("source", {view: info.viewId}) || [];
          var numSources = sources.reduce(function(memo, source) {
            return (source["source: source"] !== info.sourceId) ? memo + 1 : memo;
          }, 1);
          var fields = ixer.select("field", {view: info.viewId}) || [];
          var numFields = fields.reduce(function(memo, field) {
            return (field["field: field"] !== info.fieldId) ? memo + 1 : memo;
          }, 1);
          var selects = ixer.select("select", {view: info.viewId}) || [];
          var numSelects = selects.reduce(function(memo, select) {
            return (select["select: source"] !== info.sourceId || select["select: view field"] !== info.fieldId) ? memo + 1 : memo;
          }, 1);
          
          console.log(numSelects, "=", numFields, "*", numSources);
          
          if(numSelects !== numFields * numSources) {
            sendToServer = false;
          } else {
            diffs = diffs.concat(api.toDiffs({type: "view", content: api.retrieve("view", {view: info.viewId}), mode: "inserted"}));
          }
        }
        break;
      case "addViewSource":
        var neueSource = api.insert("source", api.diff2.source(info.sourceId, info.kind), {view: info.viewId});
        var autoJoinConstraints = api.diff2.autojoin(info.viewId, neueSource.content["source"], info.sourceId);
        
        var viewKind = (api.ixer.selectOne("view", {view: info.viewId}) || {})["view: kind"];
        if(viewKind === "union") {
          let selects = ixer.select("select", {view: info.viewId});
          if(selects.length) {
            sendToServer = false;
          }
        }
        var changes = [neueSource].concat(autoJoinConstraints);
        if(info.kind) {
          changes.push(api.remove("source", {view: info.viewId, source: info.kind}));
        }
        diffs = api.toDiffs(changes);
        break;
      case "removeViewSource":
        diffs = api.toDiffs(api.remove("source", {view: info.viewId, source: info.sourceId}));
        break;
      case "addViewConstraint":
      var rightSource = info.rightSource || info.leftSource;
      var rightField = info.rightField || info.leftField;
      diffs = api.toDiffs(api.insert("constraint", {
        view: info.viewId,
        operation: "=",
        "left source": info.leftSource,
        "left field": info.leftField,
        "right source": rightSource,
        "right field": rightField
      }));
      sendToServer = info.leftSource && info.leftField && info.rightSource && info.rightField;
{'fraction_non_alphanumeric': 0.18395251117188022, 'fraction_numerical': 0.001467351430667645, 'mean_word_length': 1.9964028776978417, 'pattern_counts': {'":': 46, '<': 19, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6778291', 'n_tokens_mistral': 4428, 'n_tokens_neox': 4396, 'n_words': 938}