triggers.js 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. // a set of utility functions for triggers
  2. Triggers = {};
  3. // Apply filters for a set of triggers
  4. // @triggers - a set of triggers
  5. // @filter - filter with array fileds with `only` and `except`
  6. // support only either `only` or `except`, but not both
  7. Triggers.applyFilters = function(triggers, filter) {
  8. if(!(triggers instanceof Array)) {
  9. triggers = [triggers];
  10. }
  11. if(!filter) {
  12. return triggers;
  13. }
  14. if(filter.only && filter.except) {
  15. throw new Error("Triggers don't support only and except filters at once");
  16. }
  17. if(filter.only && !(filter.only instanceof Array)) {
  18. throw new Error("only filters needs to be an array");
  19. }
  20. if(filter.except && !(filter.except instanceof Array)) {
  21. throw new Error("except filters needs to be an array");
  22. }
  23. if(filter.only) {
  24. return Triggers.createRouteBoundTriggers(triggers, filter.only);
  25. }
  26. if(filter.except) {
  27. return Triggers.createRouteBoundTriggers(triggers, filter.except, true);
  28. }
  29. throw new Error("Provided a filter but not supported");
  30. };
  31. // create triggers by bounding them to a set of route names
  32. // @triggers - a set of triggers
  33. // @names - list of route names to be bound (trigger runs only for these names)
  34. // @negate - negate the result (triggers won't run for above names)
  35. Triggers.createRouteBoundTriggers = function(triggers, names, negate) {
  36. var namesMap = {};
  37. _.each(names, function(name) {
  38. namesMap[name] = true;
  39. });
  40. var filteredTriggers = _.map(triggers, function(originalTrigger) {
  41. var modifiedTrigger = function(context, next) {
  42. var routeName = context.route.name;
  43. var matched = (namesMap[routeName])? 1: -1;
  44. matched = (negate)? matched * -1 : matched;
  45. if(matched === 1) {
  46. originalTrigger(context, next);
  47. }
  48. };
  49. return modifiedTrigger;
  50. });
  51. return filteredTriggers;
  52. };
  53. // run triggers and abort if redirected or callback stopped
  54. // @triggers - a set of triggers
  55. // @context - context we need to pass (it must have the route)
  56. // @redirectFn - function which used to redirect
  57. // @after - called after if only all the triggers runs
  58. Triggers.runTriggers = function(triggers, context, redirectFn, after) {
  59. var abort = false;
  60. var inCurrentLoop = true;
  61. var alreadyRedirected = false;
  62. for(var lc=0; lc<triggers.length; lc++) {
  63. var trigger = triggers[lc];
  64. trigger(context, doRedirect, doStop);
  65. if(abort) {
  66. return;
  67. }
  68. }
  69. // mark that, we've exceeds the currentEventloop for
  70. // this set of triggers.
  71. inCurrentLoop = false;
  72. after();
  73. function doRedirect(url, params, queryParams) {
  74. if(alreadyRedirected) {
  75. throw new Error("already redirected");
  76. }
  77. /*
  78. // Commenting out, so that redirects work when not in sync.
  79. // https://github.com/wekan/wekan/issues/4514
  80. if(!inCurrentLoop) {
  81. throw new Error("redirect needs to be done in sync");
  82. }
  83. */
  84. if(!url) {
  85. throw new Error("trigger redirect requires an URL");
  86. }
  87. abort = true;
  88. alreadyRedirected = true;
  89. redirectFn(url, params, queryParams);
  90. }
  91. function doStop() {
  92. abort = true;
  93. }
  94. };