Ejemplo n.º 1
0
/**
 * Filter the types loaded from a schema, first by relevant types,
 * then by the types specified in the import statement.
 *
 * @param imports Types specified in the import statement
 * @param typeDefinitions All definitions from a schema
 * @returns Filtered collection of type definitions
 */
function filterImportedDefinitions(imports, typeDefinitions) {
    // This should do something smart with fields
    var filteredDefinitions = filterTypeDefinitions(typeDefinitions);
    if (imports.includes('*')) {
        return filteredDefinitions;
    }
    else {
        var result = filteredDefinitions.filter(function (d) { return imports.map(function (i) { return i.split('.')[0]; }).includes(d.name.value); });
        var fieldImports = imports
            .filter(function (i) { return i.split('.').length > 1; });
        var groupedFieldImports = lodash_1.groupBy(fieldImports, function (x) { return x.split('.')[0]; });
        var _loop_2 = function (rootType) {
            var fields = groupedFieldImports[rootType].map(function (x) { return x.split('.')[1]; });
            filteredDefinitions.find(function (def) { return def.name.value === rootType; }).fields =
                filteredDefinitions.find(function (def) { return def.name.value === rootType; }).fields
                    .filter(function (f) { return fields.includes(f.name.value) || fields.includes('*'); });
        };
        for (var rootType in groupedFieldImports) {
            _loop_2(rootType);
        }
        return result;
    }
}
Ejemplo n.º 2
0
 morphToFetch: Promise.method(function(relationName, relatedData, options) {
   var pending = [];
   var groups = _.groupBy(this.parent, function(m) {
     return m.get(relatedData.morphName + '_type');
   });
   for (var group in groups) {
     var Target = Helpers.morphCandidate(relatedData.candidates, group);
     var target = new Target();
     pending.push(target
       .query('whereIn',
         _.result(target, 'idAttribute'),
         _.uniq(_.invoke(groups[group], 'get', relatedData.morphName + '_id'))
       )
       .sync(options)
       .select()
       .tap(eagerLoadHelper(this, relationName, {
         relatedData: relatedData.instance('morphTo', Target, {morphName: relatedData.morphName})
       }, options)));
   }
   return Promise.all(pending).then(function(resps) {
     return _.flatten(resps);
   });
 })
Ejemplo n.º 3
0
async function getSchema(){
    var table_list = await sendRequest({
        action: 'exec',
        sql: `SELECT table_name, data_type, column_name FROM information_schema.columns WHERE table_schema = database();`
    })

    return _.map(_.groupBy(table_list.results.values, k => k[0]), 
        (cols, table_name) => ({ name: table_name, columns: cols.map(k => k[2]) }) )

    // console.log(table_list)
    // var table_list = await sendRequest({
    //     action: 'exec',
    //     sql: `SELECT DISTINCT table_schema, table_name, string_agg(column_name, '<<comma>>') AS cols
    //           FROM information_schema.columns 
    //           WHERE table_schema not in ('pg_catalog', 'information_schema')
    //           GROUP BY table_schema, table_name;`
    // })
    // if(table_list.results.rows.length < 1) return [];
    // return table_list.results.rows.map(([table_schema, table_name, cols]) => {
    //     var columnNames = cols.split('<<comma>>')
    //     return { schema: table_schema, name: table_name, columns: columnNames }
    // })
}
Ejemplo n.º 4
0
function convertAndFilter(doc) {
  let countries = doc.ISO_4217.CcyTbl.CcyNtry
    // <CcyNm IsFund="true">A Name</CcyNm> puts the attribute in $.
    // Ignore funds.
    .filter((entry) => !entry.CcyNm.$)
    // <CcyMnrUnts>N.A.</CcyMnrUnts> is only used by funds, metals, and other unuseful things.
    .filter((entry) => entry.CcyMnrUnts != 'N.A.')
    // Antarctica has no currency. Ignore.
    .filter((entry) => entry.Ccy)
    .map((entry) => {
      return {
        name: entry.CtryNm,
        currencyCode: entry.Ccy,
        currencyName: entry.CcyNm,
        iso4217Id: entry.CcyNbr,
        minorUnits: entry.CcyMnrUnts
      };
    });

  console.log('Countries associated with a currency:', countries.length);

  let byCode = _.groupBy(countries, (country) => country.currencyCode);
  let currencies = _.keys(byCode).map((code) => {
    let codeCountries = byCode[code];
    let first = codeCountries[0];
    return {
      code: code,
      name: first.currencyName,
      minorUnits: first.minorUnits,
      countries: codeCountries.map((country) => _.pick(country, ['name', 'iso4217Id']))
    };
  })

  console.log('Currencies extracted', currencies.length);

  return currencies;
}
            .then(result => {
                const list = _.groupBy(result, '_id')
                let users = [];

                for (const _id in list) {
                    const userItems = list[_id]
                    const user = {
                        _id,
                        updatedAt: userItems[0].updatedAt,
                        createdAt: userItems[0].createdAt,
                        profiles: _.uniqBy(
                            userItems
                                .reduce((l, r) => l.concat(r.profiles), [])
                            , r => r.application.toString()),
                        roles: _.uniqBy(
                            userItems
                                .map(r => r.roles && _.omit(
                                    r.roles, 
                                    'createdAt', 
                                    'updatedAt', 
                                    'permissions')
                                )
                                .filter(r => r !== undefined &&
                                            r != {})
                            , r => r._id.toString()),
                        permissions: _.uniqBy(
                           userItems
                            .reduce((l, r) => l
                                .concat(r.permissions), []), r => r._id.toString())
                            .map(p => _.omit(p, 'createdAt', 'updatedAt')),
                        credentials: userItems[0].credentials
                    }; 
                    users.push(user);
                }

                resolve(users)
            })
Ejemplo n.º 6
0
    const pullFullList = () => this.list(name, (err, results, rawResult) => {
      // Already got stopped before we got started.
      if (shouldCancel) {
        if (callback) {
          callback();
        }
        return;
      }

      if (err && !rawResult) {
        this.logger.debug('Error getting list of service entries for periodic monitoring', { err });
        if (callback) {
          callback(`Error obtaining list of monitored services for periodic monitoring ${err}`);
        }
        timerId = setTimeout(pullFullList, interval);
        return;
      }

      this.logger.debug('Retrieved service list for monitor',
                        { name, results });

      // To determine if there was a change
      const newValue = _.mapValues(_.groupBy(results, 'url'), (i) => i[0]);
      const newUrls = _.keys(newValue).sort();
      const oldUrls = _.keys(this.monitoredServices[name] || {}).sort();

      if (!_.isEqual(newUrls, oldUrls)) {
        this.monitoredServices[name] = newValue;
        this.monitoredChangeId[name] = this.changeCounter;
        this.changeCounter += 1;

        if (callback) {
          callback();
        }
      }
      timerId = setTimeout(pullFullList, interval);
    });
Ejemplo n.º 7
0
  }, function(err, result) {
    var demandes = result.demandes;
    var etablissements = result.etablissements;

    if (!demandes) {
      return res.json({});
    }

    demandes.forEach(function(request) {
      request.createdAtByDay = moment(request.createdAt).format('DD/MM/YYYY');
    });

    var groupByDate = _.groupBy(demandes, 'createdAtByDay');
    var data = {dates: [], etablissements: etablissements, count: []};

    var allCount = [];
    _.forEach(groupByDate, function(demandes, date) {
      var groupByEtablissement = _.groupBy(demandes, 'etablissement');

      var idx = 0;
      etablissements.forEach(function(etablissement) {
        var demandeByEtablissement = groupByEtablissement[etablissement._id] || [];
        if (!allCount[idx]) {
          allCount[idx] = [];
        }

        allCount[idx].push(demandeByEtablissement.length);
        idx++;
      });

      data.dates.push(date);
    });

    data.count = allCount;

    return res.json(data);
  });
Ejemplo n.º 8
0
  eagerPair: function(relationName, related, parentModels) {
    var model;

    // If this is a morphTo, we only want to pair on the morphValue for the current relation.
    if (this.type === 'morphTo') {
      parentModels = _.filter(parentModels, function(model) {
        return model.get(this.key('morphKey')) === this.key('morphValue');
      }, this);
    }

    // If this is a `through` or `belongsToMany` relation, we need to cleanup & setup the `interim` model.
    if (this.isJoined()) related = this.parsePivot(related);

    // Group all of the related models for easier association with their parent models.
    var grouped = _.groupBy(related, function(model) {
      return model.pivot ? model.pivot.get(this.key('foreignKey')) :
        this.isInverse() ? model.id : model.get(this.key('foreignKey'));
    }, this);

    // Loop over the `parentModels` and attach the grouped sub-models,
    // keeping the `relatedData` on the new related instance.
    for (var i = 0, l = parentModels.length; i < l; i++) {
      model = parentModels[i];
      var groupedKey = this.isInverse() ? model.get(this.key('foreignKey')) : model.id;
      var relation = model.relations[relationName] = this.relatedInstance(grouped[groupedKey]);
      relation.relatedData = this;
    }

    // Now that related models have been successfully paired, update each with
    // its parsed attributes
    for (i = 0, l = related.length; i < l; i++) {
      model = related[i];
      model.attributes = model.parse(model.attributes);
    }

    return related;
  },
Ejemplo n.º 9
0
  /**
   * Mounting the root component.
   *
   * @internal
   * @param  {string} rootID - The root blessed ID for this node.
   * @param  {ReactBlessedReconcileTransaction} transaction
   * @param  {object} context
   */
  mountComponent(rootID, transaction, context) {
    this._rootNodeID = rootID;

    // Mounting blessed node
    const node = this.mountNode(
      ReactBlessedIDOperations.getParent(rootID),
      this._currentElement
    );

    ReactBlessedIDOperations.add(rootID, node);

    // Mounting children
    let childrenToUse = this._currentElement.props.children;
    childrenToUse = childrenToUse === null ? [] : [].concat(childrenToUse);

    if (childrenToUse.length) {

      // Discriminating content components from real children
      const {content=null, realChildren=[]} = groupBy(childrenToUse, (c) => {
        return CONTENT_TYPES[typeof c] ? 'content' : 'realChildren';
      });

      // Setting textual content
      if (content)
        node.setContent('' + content.join(''));

      // Mounting real children
      this.mountChildren(
        realChildren,
        transaction,
        context
      );
    }

    // Rendering the screen
    ReactBlessedIDOperations.screen.debouncedRender();
  }
Ejemplo n.º 10
0
/**
 * Given a dependencies collection, returns whether the user prefers ^, ~, .*, or .x (simply counts the greatest number of occurences).
 */
function getPreferredWildcard(dependencies) {

    // group the dependencies by wildcard
    var groups = _.groupBy(_.values(dependencies), function (dep) {
        return _.find(WILDCARDS, function (wildcard) {
                return dep.indexOf(wildcard) > -1;
            }) || DEFAULT_WILDCARD;
    });

    // convert to an array of objects that can be sorted
    var arrOfGroups = cint.toArray(groups, function (wildcard, instances) {
        return {
            wildcard: wildcard,
            instances: instances
        };
    });

    // reverse sort the groups so that the wildcard with the most appearances is at the head, then return it.
    var sorted = _.sortBy(arrOfGroups, function (wildcardObject) {
        return -wildcardObject.instances.length;
    });

    return sorted[0].wildcard;
}
Ejemplo n.º 11
0
            root.getArrayTree({sort: { orderBy: 1 }},function(err,docs){
                if (Options.sync){
                    var asyncArr = [];
                    //This is where things get interesting. We need to fetch all items and go find their current
                    //values in the DB
                    var flatTree = flattenTree(docs[0].children);

                    //Create a group of arrays per model
                    var groups = lo.groupBy(flatTree,'model');
                    //loop the groups and look up for the actual data
                    for (var model in groups){

                        asyncArr.push(getActualItem.bind(null,model,groups[model]));

                    }

                    //replace
                    async.parallel(asyncArr,function(error,results){
                        var sorted = [];
                       next(null,sortBy(docs[0].children,'orderBy','') || []);
                    });
                    //console.log(docs[0].children)
                }
            });
Ejemplo n.º 12
0
      .map(function(village) {
        if (village.legions) {
          village.legions = _.map(village.legions, function(legion) {
            var leg = legion.match(/^(\w+) (\w+) (\w+|\w+ Guild) x (\d+)$/);
            if (!leg) {
              return legion;
            }
            var name = leg[1];
            var structure = leg[2];
            var commander = leg[3];
            var size = leg[4];
            return {
              name: name,
              structure: structure,
              commander: commander,
              size: size
            };
          });

          village.legionsByCommand = _.map(_.groupBy(village.legions, "commander"), function(commander, key) {
            var count = _.sum(_.pluck(commander, "size"));
            return {
              commander: key,
              size: count
            };
          });
        }

        if (village.occupied === 'conquered') {
          village.governance = village.city;
        } else if (village.occupied === 'not' && village.city === 'independent') {
          village.governance = '';
        } else {
          village.governance = 'disputed';
        }
      })
Ejemplo n.º 13
0
            return Promise.all(photosWithUrlsPromise).then(photosWithUrls => {
                console.log('Photos with sharing URL', photosWithUrls.length)

                let photosMap = _.groupBy(photos, 'id')
                let photosWithUrlsMap = _.chain(photosWithUrls)
                    .map(photo => photo.links[0])
                    .compact()
                    .groupBy('id')
                    .value()

                return _.chain(photosMap)
                    .map((val, id) => {
                        if (!photosWithUrlsMap[id]) {
                            return null;
                        }

                        const parsedUrl = url.parse(photosWithUrlsMap[id][0].url)
                        val[0].url = 'https://dl.dropboxusercontent.com' + parsedUrl.pathname

                        return val[0];
                    })
                    .compact()
                    .value()
            }, err => {
Ejemplo n.º 14
0
__private.squashQueue = function (broadcasts) {
	var grouped = _.groupBy(broadcasts, function (broadcast) {
		return broadcast.options.api;
	});

	var squashed = [];

	self.routes.forEach(function (route) {
		if (Array.isArray(grouped[route.path])) {
			var data = {};

			data[route.collection] = grouped[route.path].map(function (broadcast) {
				return broadcast.options.data[route.object];
			}).filter(Boolean);

			squashed.push({
				options: { api: route.path, data: data, method: route.method },
				immediate: false
			});
		}
	});

	return squashed;
};
Ejemplo n.º 15
0
function parseMiddlewares(spec, middlewares) {
    let methods = _.groupBy(middlewares, (layer) => {
        return layer.method || 'all';
    });

    _.each(methods.all, (middleware) => {
        _.each(spec, (value, key) => {
            spec[key].responses = spec[key].responses || {};
            spec[key].responses['500'] = { $ref: '#/responses/ServerError' };
            spec[key] = parseMiddleware(spec[key], middleware);
        });
    });

    _.each(_.omit(methods, 'all'), (group, method) => {
        spec[method].responses = spec[method].responses || {};
        spec[method].responses['500'] = { $ref: '#/responses/ServerError' };

        _.each(group, (middleware) => {
            parseMiddleware(spec[method], middleware);
        });
    });

    return spec;
}
Ejemplo n.º 16
0
  .then((image) => {
    const fileName = Date.now() + "-firefox-" + encodeURIComponent(pageUrl) + ".png";
    fs.writeFileSync("./screenshots/" + fileName, image, "base64")
    const files = fs.readdirSync("./screenshots/")
    const history = _.groupBy(files, (val) => {
      return val.split("-")[2]
    })

    _.forEach(history, (value, key) => {
      let url = key.split(".")
      url.pop()
      url = url.join(".")
      const currentVersion = value.pop();
      const previousVersion = value.pop();

      if (previousVersion && currentVersion) {
        const diffFileName = "./diffs/" + Date.now() + "-" + encodeURIComponent(pageUrl) + ".png";
        imageDiff({
          actualImage: "./screenshots/" + currentVersion,
          expectedImage: "./screenshots/" + previousVersion,
          diffImage: diffFileName,
        }, function (err, imagesAreSame) {
          if (err) {
            console.log(err)
            return;
          }
          if (imagesAreSame) {
            console.log("No changes to previous detected")
            fs.unlink("./screenshots/" + currentVersion)
            fs.unlink(diffFileName)
          }
        });
      }
    })
    driver.quit();
  });
Ejemplo n.º 17
0
export function tabifyGetColumns(aggs, minimal, hierarchical) {

  if (minimal == null) minimal = !hierarchical;

  // pick the columns
  if (minimal) {
    return aggs.map(function (agg) {
      return { aggConfig: agg };
    });
  }

  // supposed to be bucket,...metrics,bucket,...metrics
  const columns = [];

  // seperate the metrics
  const grouped = _.groupBy(aggs, function (agg) {
    return agg.schema.group;
  });

  if (!grouped.buckets) {
    // return just the metrics, in column format
    return grouped.metrics.map(function (agg) {
      return { aggConfig: agg };
    });
  }

  // return the buckets, and after each place all of the metrics
  grouped.buckets.forEach(function (agg) {
    columns.push({ aggConfig: agg });
    grouped.metrics.forEach(function (metric) {
      columns.push({ aggConfig: metric });
    });
  });

  return columns;
}
Ejemplo n.º 18
0
 cursor.toArray(function(err, data) {
   var points = _.groupBy(data, 'point')
   var response = { points: [] }
   for (var p in points) {
     var obj = {
       point: p,
       projects: points[p].length
     }
     technology_fields.forEach(function(technology_field) {
       var techs = _.filter(_.uniq(_.pluck(points[p], technology_field)), null)
       var techcount = []
       techs.forEach(function(tech) {
         var where = {}
         where[technology_field] = tech
         var x = {t: tech}
         x.p = _.where(points[p], where).length
         techcount.push(x)
       })
       obj[technology_field] = techcount
     })
     response.points.push(obj)
   }
   returnData(req, res, response)
 })
Ejemplo n.º 19
0
Tree.prototype.process = function () {
    const levels = _.groupBy(this.nodes, function (node) {
        return node.height();
    });

    const hashAlgo = this.hashAlgo;
    let level, node, name;
    for (let height = 0, maxHeight = _.size(levels) - 1; height <= maxHeight; height++) {
        level = levels[height];
        for (let i = 0, len = level.length; i < len; i++) {
            node = level[i];
            name = node.name;

            // Should be done before hashing and renaming!
            node.updateDependencyReferences();

            node.marks = null;
            node.ast = null;

            if (_.contains(this.noRename, name))
                continue;

            node.hash = crypto.createHash(hashAlgo)
                              .update(fs.readFileSync(name))
                              .digest('hex');
            node.name = normalizePath(
                path.dirname(name) + '/' +
                path.basename(name, node.ext) + '.' + node.hash + node.ext
            );

            fs.renameSync(name, node.name);
        }
    }

    return this;
};
Ejemplo n.º 20
0
  getTrends(items, timeFrom, timeTill, options) {
    let { intervalMs, consolidateBy } = options;
    let intervalSec = Math.ceil(intervalMs / 1000);

    consolidateBy = consolidateBy || 'avg';
    let aggFunction = dbConnector.consolidateByFunc[consolidateBy];

    // Group items by value type and perform request for each value type
    let grouped_items = _.groupBy(items, 'value_type');
    let promises = _.map(grouped_items, (items, value_type) => {
      let itemids = _.map(items, 'itemid').join(', ');
      let table = TREND_TO_TABLE_MAP[value_type];
      let valueColumn = _.includes(['avg', 'min', 'max', 'sum'], consolidateBy) ? consolidateBy : 'avg';
      valueColumn = dbConnector.consolidateByTrendColumns[valueColumn];
      let query = this.sqlDialect.trendsQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction, valueColumn);

      query = compactQuery(query);
      return this.invokeSQLQuery(query);
    });

    return Promise.all(promises).then(results => {
      return _.flatten(results);
    });
  }
Ejemplo n.º 21
0
function makeD3tree(dzrokhebi) {
  dzrokhebi = dzrokhebi.map(v => {
    return {
      name: v.skesi + '-' + v.n,
      skesi: v.skesi,
      ojakhi: v.mama + ' da ' + v.deda,
      ojakhebi: v.skesi !== 'ფური' ? Object.keys(v.ojakhebi).map(key => v.n + ' da ' + key) : undefined,
      size: Math.floor((Date.now() - new Date(v.dabDge)) / 1000 / 60 / 60 / 24)
    };
  });
  var ns = {};
  var getNode = (name) => ns[name] ? ns[name] : (ns[name] = {name: '', children: []}, ns[name]);
  for(var d of dzrokhebi){
    if(d.ojakhebi){
      getNode(d.ojakhi).children.push(
        {name:'', children: d.ojakhebi.map(o => getNode(o)).concat([d])}
      );
    } else {
      getNode(d.ojakhi).children.push(d);
    }
  }
  var ojakhebi =  _.groupBy(dzrokhebi, g => g.ojakhi);
  return ns['adam da eva'];
}
Ejemplo n.º 22
0
  it('renders ns records', () => {
    const currentZone = domains.domains[1];
    const nsRecords = Object.values(currentZone._records.records).filter(
      r => r.type === 'NS');

    const page = mount(
      <ZonePage
        dispatch={dispatch}
        domain={{
          ...currentZone,
          _groupedRecords: _.groupBy(currentZone._records.records, 'type'),
        }}
      />
    );

    const nsRows = page.find('#ns .TableRow');
    expect(nsRows.length).to.equal(5);
    const nsValues = nsRows.at(4).find('td');
    expect(nsValues.length).to.equal(4);
    // Test all values in an NS row
    const nsRecord = nsRecords[0];
    [nsRecord.target, nsRecord.name || currentZone.domain,
      '86400 (1 day)'].forEach((value, i) => expect(nsValues.at(i).text()).to.equal(value));
  });
Ejemplo n.º 23
0
  _.each(dkeys, function(d) {
    aa = dsched[d]
    console.log('\n\n=== '+d+' ===')
    var fsched = _.groupBy(aa, function(o) {
      var ven = o.venue
      var fno = o.fno
      if ( ven.match(/Cardiff ES/ ) ) {
        ven = 'Berkich Park'
        fno = 2
      }
      return ven + ' #' + fno
    })

    fkeys = _.keys(fsched).sort()
    _.each(fkeys, function(f) {
      var a = fsched[f]    
      console.log("\n > "+f+' <')
      var last = moment('1970-01-01','YYYY-MM-DD')
      _.each(_.sortBy(a,'start'), function(g) {
        console.log(format_game(g,last))
        last = moment(g.end)
      });
    });
  });
Ejemplo n.º 24
0
function getGruppenWithSameJugend(gruppen) {
    const jugenden = _.groupBy(gruppen, 'jugend._id');
    return _.pickBy(jugenden, function (jugend) {
        return jugend.length > 1;
    });
}
Ejemplo n.º 25
0
      function sendChanges(changes, cbSendChanges) {
          console.log('PUSHING!')
          ss.add(changes)
          ss.send(cbSendChanges)
      }

    ], function errorWaterfall(err) {
      if ( err ) throw new Error(err)
      console.log("DONE")
    })
  }

} else if ( argv.format == 'day' ) {
  var dsched = _.groupBy(sched, function(o) {
    return moment(o.d).format('dddd, MMMM DD, YYYY')
  })
  dkeys = _.keys(dsched).sort(function(a,b) {
    return moment(a,'dddd, MMMM DD, YYYY') - moment(b,'dddd, MMMM DD, YYYY')
  })
  if ( argv.from ) {
    dkeys = _.filter(dkeys,function(d) { return moment(d,'dddd, MMMM DD, YYYY') > moment(argv.from,'YYYY-MM-DD') })
  }
  _.each(dkeys, function(d) {
    aa = dsched[d]
    console.log('\n\n=== '+d+' ===')
    var fsched = _.groupBy(aa, function(o) {
      var ven = o.venue
      var fno = o.fno
      if ( ven.match(/Cardiff ES/ ) ) {
        ven = 'Berkich Park'
Ejemplo n.º 26
0
 self.getLangsLearnt = function() {
   return _.keys(_.groupBy(self.userList, function(word) { return word.lang; })).length;
 };
Ejemplo n.º 27
0
/**
 * In order to generate swagger for all methods they must be grouped by URL, and type(get, put, delete) is subobject
 * See swagger specs for details.
 * @param apidocJson
 * @returns {*}
 */
function groupByUrl(apidocJson) {
  return _.groupBy(apidocJson, function (b) {
    return b.url;
  });
}
Ejemplo n.º 28
0
	createDropdown() {
		const element = string.html`
			<div class="res-filterline-dropdown">
				<div class="res-filterline-dropdown-other"></div>
				<div class="res-filterline-dropdown-toggles">
					<div class="res-filterline-display-match-reason">
						<label>
							<input type="checkbox" ${this.displayReasons && 'checked'}">
							<span>Show matching filters</span>
						</label>
					</div>
				</div>
				<div class="res-filterline-show-help">
					Usage information
				</div>
			</div>
		`;

		this.preamble.append(element);

		// Hover cards may be in front of the dropdown
		this.preamble.addEventListener('mouseenter', () => {
			Hover.infocard('filterline-filter').close();
		});

		function addDetails(summary, className: string, ...elements) {
			const e = string.html`<details class="${className}"><summary>${summary}</summary></details>`;
			e.append(...elements);
			element.querySelector('.res-filterline-dropdown-other').append(e);
		}

		addDetails('Modify external filters', 'res-filterline-external',
			...this.filters
				.filter(filter => filter instanceof ExternalFilter)
				.map(filter => { filter.createElement(); return filter.element; })
		);

		// `Cases.Group` is separated
		const dp = _.groupBy(_.without(this.getPickable(), Cases.Group), v => v.variant);
		for (const [name, CaseClasses] of Object.entries(dp)) {
			addDetails(`New ${name} filter`, `res-filterline-new-${name}`,
				...CaseClasses
					.sort((a, b) => a.type.localeCompare(b.type))
					.map(CaseClass => this.createNewFilterElement(CaseClass))
			);
		}

		const _getAsConditions = this.getAsConditions.bind(this);
		addDetails('New complex filter', 'res-filterline-new-group',
			this.createNewFilterElement(Cases.Group, 'Copy active filters', { get conditions() { return _getAsConditions(); } }),
			...Cases.Group.fields[0].options
				.map(op => this.createNewFilterElement(Cases.Group, `Matches ${op}`, { conditions: { op, of: [] } }))
		);

		addDetails('Use as default', 'res-filterline-set-default',
			...FilteReddit.defaultFilters.map(({ type, text }) => {
				const e = string.html`<div class="res-filterline-dropdown-action">${text}</div>`;
				e.addEventListener('click', () => FilteReddit.saveFilterlineStateAsDefault(type));
				return e;
			}),
			(() => {
				const e = string.html`<div class="res-filterline-dropdown-action">Reset this Filterline</div>`;
				e.addEventListener('click', () => {
					this.storage.delete();
					if (confirm('Reload page to restore default')) location.reload();
				});
				return e;
			})()
		);

		const displayReasonsCheckbox = downcast(element.querySelector('.res-filterline-display-match-reason input'), HTMLInputElement);
		displayReasonsCheckbox.addEventListener('change', () => {
			this.toggleDisplayReasons(displayReasonsCheckbox.checked);
		});

		if (this.thingType === 'post' && loggedInUser()) {
			const permanentlyHide = string.html`
				<div class="res-filterline-permanently-hide">
					<label>
						<input type="checkbox">
						<span>Permanently hide</span>
					</label>
				</div>
			`;
			const checkbox = this.permanentlyHideCheckbox = downcast(permanentlyHide.querySelector('input'), HTMLInputElement);
			this.updatePermanentlyHideCheckbox();
			permanentlyHide.addEventListener('click', async () => {
				checkbox.disabled = true;
				await (this.permanentlyHiddenThings.size ? this.unhidePermanently() : this.hidePermanently());
				checkbox.disabled = false;
			});
			element.querySelector('.res-filterline-dropdown-toggles').append(permanentlyHide);
		}

		downcast(element.querySelector('.res-filterline-show-help'), HTMLElement).addEventListener('click', () => {
			RESTips.showFeatureTip('filterlineVisible');
		});
	}
Ejemplo n.º 29
0
export default function( editor ) {
	const getContent = this.getContent.bind( this );
	const { setTimeout, onReplace } = this.props;

	const VK = tinymce.util.VK;
	const settings = editor.settings.wptextpattern || {};

	const {
		enter: enterPatterns,
		undefined: spacePatterns,
	} = groupBy( filter( getBlockTransforms( 'from' ), { type: 'pattern' } ), 'trigger' );

	const inlinePatterns = settings.inline || [
		{ delimiter: '`', format: 'code' },
	];

	let canUndo;

	editor.on( 'selectionchange', function() {
		canUndo = null;
	} );

	editor.on( 'keydown', function( event ) {
		const { keyCode } = event;

		if ( ( canUndo && keyCode === ESCAPE ) || ( canUndo === 'space' && keyCode === BACKSPACE ) ) {
			editor.undoManager.undo();
			event.preventDefault();
			event.stopImmediatePropagation();
		}

		if ( VK.metaKeyPressed( event ) ) {
			return;
		}

		if ( keyCode === ENTER ) {
			enter( event );
		// Wait for the browser to insert the character.
		} else if ( keyCode === SPACE ) {
			setTimeout( () => searchFirstText( spacePatterns ) );
		} else if ( keyCode > 47 && ! ( keyCode >= 91 && keyCode <= 93 ) ) {
			setTimeout( inline );
		}
	}, true );

	function inline() {
		const range = editor.selection.getRng();
		const node = range.startContainer;
		const carretOffset = range.startOffset;

		// We need a non empty text node with an offset greater than zero.
		if ( ! node || node.nodeType !== 3 || ! node.data.length || ! carretOffset ) {
			return;
		}

		const textBeforeCaret = node.data.slice( 0, carretOffset );
		const charBeforeCaret = node.data.charAt( carretOffset - 1 );

		const { start, pattern } = inlinePatterns.reduce( ( acc, item ) => {
			if ( acc.result ) {
				return acc;
			}

			if ( charBeforeCaret !== item.delimiter.slice( -1 ) ) {
				return acc;
			}

			const escapedDelimiter = escapeRegExp( item.delimiter );
			const regExp = new RegExp( '(.*)' + escapedDelimiter + '.+' + escapedDelimiter + '$' );
			const match = textBeforeCaret.match( regExp );

			if ( ! match ) {
				return acc;
			}

			const startOffset = match[ 1 ].length;
			const endOffset = carretOffset - item.delimiter.length;
			const before = textBeforeCaret.charAt( startOffset - 1 );
			const after = textBeforeCaret.charAt( startOffset + item.delimiter.length );
			const delimiterFirstChar = item.delimiter.charAt( 0 );

			// test*test* => format applied
			// test *test* => applied
			// test* test* => not applied
			if ( startOffset && /\S/.test( before ) ) {
				if ( /\s/.test( after ) || before === delimiterFirstChar ) {
					return acc;
				}
			}

			const contentRegEx = new RegExp( '^[\\s' + escapeRegExp( delimiterFirstChar ) + ']+$' );
			const content = textBeforeCaret.slice( startOffset, endOffset );

			// Do not replace when only whitespace and delimiter characters.
			if ( contentRegEx.test( content ) ) {
				return acc;
			}

			return {
				start: startOffset,
				pattern: item,
			};
		}, {} );

		if ( ! pattern ) {
			return;
		}

		const { delimiter, format } = pattern;
		const formats = editor.formatter.get( format );

		if ( ! formats || ! formats[ 0 ].inline ) {
			return;
		}

		editor.undoManager.add();
		editor.undoManager.transact( () => {
			node.insertData( carretOffset, '\uFEFF' );

			const newNode = node.splitText( start );
			const zero = newNode.splitText( carretOffset - start );

			newNode.deleteData( 0, delimiter.length );
			newNode.deleteData( newNode.data.length - delimiter.length, delimiter.length );

			editor.formatter.apply( format, {}, newNode );
			editor.selection.setCursorLocation( zero, 1 );

			// We need to wait for native events to be triggered.
			setTimeout( () => {
				canUndo = 'space';

				editor.once( 'selectionchange', () => {
					if ( zero ) {
						const zeroOffset = zero.data.indexOf( '\uFEFF' );

						if ( zeroOffset !== -1 ) {
							zero.deleteData( zeroOffset, zeroOffset + 1 );
						}
					}
				} );
			} );
		} );
	}

	function searchFirstText( patterns ) {
		if ( ! onReplace ) {
			return;
		}

		// Merge text nodes.
		editor.getBody().normalize();

		const content = getContent();

		if ( ! content.length ) {
			return;
		}

		const firstText = content[ 0 ];

		const transformation = findTransform( patterns, ( item ) => {
			return item.regExp.test( firstText );
		} );

		if ( ! transformation ) {
			return;
		}

		const result = firstText.match( transformation.regExp );

		const range = editor.selection.getRng();
		const matchLength = result[ 0 ].length;
		const remainingText = firstText.slice( matchLength );

		// The caret position must be at the end of the match.
		if ( range.startOffset !== matchLength ) {
			return;
		}

		const block = transformation.transform( {
			content: [ remainingText, ...drop( content ) ],
			match: result,
		} );

		onReplace( [ block ] );
	}

	function enter( event ) {
		if ( ! onReplace ) {
			return;
		}

		// Merge text nodes.
		editor.getBody().normalize();

		const content = getContent();

		if ( ! content.length ) {
			return;
		}

		const pattern = findTransform( enterPatterns, ( { regExp } ) => regExp.test( content[ 0 ] ) );

		if ( ! pattern ) {
			return;
		}

		const block = pattern.transform( { content } );
		onReplace( [ block ] );

		// We call preventDefault to prevent additional newlines.
		event.preventDefault();
		// stopImmediatePropagation is called to prevent TinyMCE's own processing of keydown which conflicts with the block replacement.
		event.stopImmediatePropagation();
	}
}
 let groupBy = _.curry((key, coll) => {
   return _.groupBy(coll, key);
 });