wuffle 0.53.1 → 0.55.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -13,9 +13,9 @@ Refer to the [project documentation](https://github.com/nikku/wuffle#readme) for
13
13
 
14
14
  ## Usage
15
15
 
16
- Run your own [Wuffle Board](https://github.com/nikku/wuffle) via `npx`:
16
+ Run your own [Wuffle](https://github.com/nikku/wuffle) instance via `npx`:
17
17
 
18
- ```
18
+ ```sh
19
19
  npx wuffle
20
20
  ```
21
21
 
@@ -49,12 +49,22 @@ module.exports = function(webhookEvents, githubIssues, columns) {
49
49
  ]);
50
50
  });
51
51
 
52
- webhookEvents.on('pull_request.ready_for_review', async (context) => {
52
+ webhookEvents.on([
53
+ 'pull_request.ready_for_review',
54
+ 'pull_request.review_requested'
55
+ ], async (context) => {
53
56
 
54
57
  const {
55
- pull_request
58
+ pull_request,
59
+ action
56
60
  } = context.payload;
57
61
 
62
+ // do not forcefully move draft PRs into review,
63
+ // these shall be marked as _ready for review_ first
64
+ if (action === 'review_requested' && pull_request.draft) {
65
+ return;
66
+ }
67
+
58
68
  const state = isExternal(pull_request) ? EXTERNAL_CONTRIBUTION : IN_REVIEW;
59
69
 
60
70
  const column = columns.getByState(state);
@@ -62,11 +62,7 @@ module.exports = async (
62
62
  }
63
63
 
64
64
  function getIssueSearchFilter(req) {
65
- const s = req.query.s;
66
-
67
- if (!s) {
68
- return null;
69
- }
65
+ const s = req.query.s || null;
70
66
 
71
67
  const user = authRoutes.getGitHubUser(req);
72
68
 
@@ -99,7 +95,7 @@ module.exports = async (
99
95
  };
100
96
  });
101
97
 
102
- const searchFiltered = searchFilter ? accessFiltered.filter(searchFilter) : accessFiltered;
98
+ const searchFiltered = accessFiltered.filter(searchFilter);
103
99
 
104
100
  filteredItems[columnKey] = searchFiltered.map(filterIssueOrPull);
105
101
 
@@ -134,7 +130,7 @@ module.exports = async (
134
130
  };
135
131
  });
136
132
 
137
- const searchFiltered = searchFilter ? accessFiltered.map(update => {
133
+ const searchFiltered = accessFiltered.map(update => {
138
134
 
139
135
  if (searchFilter(update.issue)) {
140
136
  return update;
@@ -146,7 +142,7 @@ module.exports = async (
146
142
  ...update,
147
143
  type: 'remove'
148
144
  };
149
- }) : accessFiltered;
145
+ });
150
146
 
151
147
  return searchFiltered.map(update => {
152
148
 
@@ -1,7 +1,7 @@
1
1
  const fs = require('fs').promises;
2
2
  const path = require('path');
3
3
 
4
- const mkdirp = require('mkdirp');
4
+ const { mkdirp } = require('mkdirp');
5
5
 
6
6
 
7
7
  /**
@@ -1,4 +1,4 @@
1
- const mkdirp = require('mkdirp');
1
+ const { mkdirp } = require('mkdirp');
2
2
 
3
3
  const path = require('path');
4
4
  const fs = require('fs').promises;
@@ -16,16 +16,20 @@ const CHILD_LINK_TYPES = {
16
16
  [ LinkTypes.CLOSES ]: true
17
17
  };
18
18
 
19
+ /**
20
+ * @typedef { { defaultFilter?: string } } SearchConfig
21
+ */
19
22
 
20
23
  /**
21
24
  * This app allows you to create a search filter from a given term.
22
25
  *
23
26
  * @constructor
24
27
  *
28
+ * @param {SearchConfig} config
25
29
  * @param {import('../../types').Logger} logger
26
30
  * @param {import('../../store')} store
27
31
  */
28
- function Search(logger, store) {
32
+ function Search(config, logger, store) {
29
33
 
30
34
  const log = logger.child({
31
35
  name: 'wuffle:search'
@@ -47,19 +51,25 @@ function Search(logger, store) {
47
51
  return filterReject;
48
52
  }
49
53
 
50
- function includes(actual, pattern) {
51
- return pattern && actual.toLowerCase().includes(pattern.toLowerCase());
52
- }
54
+ /**
55
+ * @param { string } actual
56
+ * @param { string } pattern
57
+ * @param { boolean } [exact=false]
58
+ *
59
+ * @return { boolean }
60
+ */
61
+ function includes(actual, pattern, exact) {
53
62
 
54
- function fuzzyMatches(actual, pattern) {
55
- return pattern && actual.toLowerCase().startsWith(pattern.toLowerCase());
63
+ if (exact) {
64
+ return pattern && actual === pattern;
65
+ }
66
+
67
+ return pattern && actual.toLowerCase().includes(pattern.toLowerCase());
56
68
  }
57
69
 
58
70
  const filters = {
59
71
 
60
- text: function textFilter(text) {
61
-
62
- text = text.toLowerCase();
72
+ text: function textFilter(text, exact) {
63
73
 
64
74
  return function filterText(issue) {
65
75
  const issueText = `#${issue.number} ${issue.title}\n\n${issue.body}`;
@@ -129,26 +139,26 @@ function Search(logger, store) {
129
139
  }
130
140
  },
131
141
 
132
- label: function labelFilter(name) {
142
+ label: function labelFilter(name, exact) {
133
143
  return function filterLabel(issue) {
134
144
 
135
145
  const { labels } = issue;
136
146
 
137
- return (labels || []).some(label => includes(label.name, name));
147
+ return (labels || []).some(label => includes(label.name, name, exact));
138
148
  };
139
149
  },
140
150
 
141
- repo: function repoFilter(name) {
151
+ repo: function repoFilter(name, exact) {
142
152
 
143
153
  return function filterRepoAndOwner(issue) {
144
154
 
145
155
  const { repository } = issue;
146
156
 
147
- return includes(`${repository.owner.login}/${repository.name}`, name);
157
+ return includes(`${repository.owner.login}/${repository.name}`, name, exact);
148
158
  };
149
159
  },
150
160
 
151
- milestone: function milestoneFilter(name) {
161
+ milestone: function milestoneFilter(name, exact) {
152
162
 
153
163
  return function filterMilestone(issue) {
154
164
 
@@ -156,11 +166,11 @@ function Search(logger, store) {
156
166
  milestone
157
167
  } = issue;
158
168
 
159
- return milestone && fuzzyMatches(milestone.title, name);
169
+ return milestone && includes(milestone.title, name, exact);
160
170
  };
161
171
  },
162
172
 
163
- author: function authorFilter(name) {
173
+ author: function authorFilter(name, exact) {
164
174
 
165
175
  return function filterAuthor(issue) {
166
176
 
@@ -168,11 +178,11 @@ function Search(logger, store) {
168
178
  user
169
179
  } = issue;
170
180
 
171
- return user && fuzzyMatches(user.login, name);
181
+ return user && includes(user.login, name, exact);
172
182
  };
173
183
  },
174
184
 
175
- assignee: function assigneeFilter(name) {
185
+ assignee: function assigneeFilter(name, exact) {
176
186
 
177
187
  return function filterAssignee(issue) {
178
188
 
@@ -180,11 +190,11 @@ function Search(logger, store) {
180
190
  assignees
181
191
  } = issue;
182
192
 
183
- return (assignees || []).some(assignee => fuzzyMatches(assignee.login, name));
193
+ return (assignees || []).some(assignee => includes(assignee.login, name, exact));
184
194
  };
185
195
  },
186
196
 
187
- reviewer: function reviewerFilter(name) {
197
+ reviewer: function reviewerFilter(name, exact) {
188
198
 
189
199
  return function filterReviewer(issue) {
190
200
 
@@ -199,14 +209,14 @@ function Search(logger, store) {
199
209
  }
200
210
 
201
211
  return (
202
- requested_reviewers.some(reviewer => fuzzyMatches(reviewer.login, name))
212
+ requested_reviewers.some(reviewer => includes(reviewer.login, name, exact))
203
213
  ) || (
204
- (reviews || []).some(review => fuzzyMatches(review.user.login, name))
214
+ (reviews || []).some(review => includes(review.user.login, name, exact))
205
215
  );
206
216
  };
207
217
  },
208
218
 
209
- commented: function commentedFilter(name) {
219
+ commented: function commentedFilter(name, exact) {
210
220
 
211
221
  return function filterCommented(issue) {
212
222
 
@@ -220,17 +230,17 @@ function Search(logger, store) {
220
230
  }
221
231
 
222
232
  return (
223
- comments.some(comment => fuzzyMatches(comment.user.login, name))
233
+ comments.some(comment => includes(comment.user.login, name))
224
234
  );
225
235
  };
226
236
  },
227
237
 
228
- involves: function involvesFilter(name) {
238
+ involves: function involvesFilter(name, exact) {
229
239
 
230
- const isAssigned = filters.assignee(name);
231
- const isAuthor = filters.author(name);
232
- const isReviewer = filters.reviewer(name);
233
- const hasCommented = filters.commented(name);
240
+ const isAssigned = filters.assignee(name, exact);
241
+ const isAuthor = filters.author(name, exact);
242
+ const isReviewer = filters.reviewer(name, exact);
243
+ const hasCommented = filters.commented(name, exact);
234
244
 
235
245
  return function filterInvolves(issue) {
236
246
  return (
@@ -289,23 +299,16 @@ function Search(logger, store) {
289
299
  };
290
300
  }
291
301
 
292
- /**
293
- * Retrieve a filter function from the given search string.
294
- *
295
- * @param {string} search
296
- * @param {import('../../types').GitHubUser} [user]
297
- *
298
- * @return {Function}
299
- */
300
- function getSearchFilter(search, user) {
302
+ function buildFilterFns(search, user) {
301
303
 
302
- const terms = parseSearch(search);
304
+ const terms = search ? parseSearch(search) : [];
303
305
 
304
- const filterFns = terms.map(term => {
306
+ return terms.map(term => {
305
307
  let {
306
308
  qualifier,
307
309
  value,
308
- negated
310
+ negated,
311
+ exact
309
312
  } = term;
310
313
 
311
314
  if (!value) {
@@ -318,6 +321,7 @@ function Search(logger, store) {
318
321
  }
319
322
 
320
323
  value = user.login;
324
+ exact = true;
321
325
  }
322
326
 
323
327
  const factoryFn = filters[qualifier];
@@ -326,7 +330,7 @@ function Search(logger, store) {
326
330
  return noopFilter();
327
331
  }
328
332
 
329
- const fn = factoryFn(value);
333
+ const fn = factoryFn(value, exact);
330
334
 
331
335
  if (negated) {
332
336
  return function(arg) {
@@ -336,10 +340,30 @@ function Search(logger, store) {
336
340
 
337
341
  return fn;
338
342
  });
343
+ }
344
+
345
+ /**
346
+ * Retrieve a filter function from the given search string.
347
+ *
348
+ * @param {string} search
349
+ * @param {import('../../types').GitHubUser} [user]
350
+ *
351
+ * @return {Function}
352
+ */
353
+ function getSearchFilter(search, user) {
354
+
355
+ const filterFns = buildFilterFns(search, user);
356
+
357
+ const ignoreFilterFns = buildFilterFns(config.defaultFilter, user);
339
358
 
340
359
  return function(issue) {
341
360
  try {
342
- return filterFns.every(fn => fn(issue));
361
+ if (filterFns.length) {
362
+ return filterFns.every(fn => fn(issue));
363
+ } else {
364
+
365
+ return ignoreFilterFns.every(fn => fn(issue));
366
+ }
343
367
  } catch (err) {
344
368
  log.warn({ issue: issueIdent(issue), err }, 'filter failed');
345
369
 
@@ -57,6 +57,16 @@ function startOfDay(time) {
57
57
  return date.getTime();
58
58
  }
59
59
 
60
+ /**
61
+ * @param {string} str
62
+ *
63
+ * @return { {
64
+ * qualifier: string,
65
+ * value: string|undefined,
66
+ * exact: boolean,
67
+ * negated?: boolean
68
+ * }[] }
69
+ */
60
70
  function parseSearch(str) {
61
71
 
62
72
  const regexp = /(?:([\w#/&]+)|"([\w#/&\s-.]+)"|([-!]?)([\w]+):(?:([\w-#/&@<>=.]+)|"([\w-#/&@:.,; ]+)")?)(?:\s|$)/g;
@@ -83,7 +93,8 @@ function parseSearch(str) {
83
93
  if (textValue) {
84
94
  terms.push({
85
95
  qualifier: 'text',
86
- value: textValue
96
+ value: textValue,
97
+ exact: !!textEscaped
87
98
  });
88
99
  }
89
100
 
@@ -93,7 +104,8 @@ function parseSearch(str) {
93
104
  terms.push({
94
105
  qualifier,
95
106
  value: qualifierValue,
96
- negated: !!negated
107
+ negated: !!negated,
108
+ exact: !!qualifierTextEscaped
97
109
  });
98
110
  }
99
111
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wuffle",
3
- "version": "0.53.1",
3
+ "version": "0.55.0",
4
4
  "description": "A multi-repository task board for GitHub issues",
5
5
  "author": {
6
6
  "name": "Nico Rehwaldt",
@@ -43,31 +43,30 @@
43
43
  "express-session": "^1.17.3",
44
44
  "fake-tag": "^3.0.0",
45
45
  "memorystore": "^1.6.7",
46
- "min-dash": "^3.8.1",
47
- "mkdirp": "^1.0.4",
46
+ "min-dash": "^4.1.1",
47
+ "mkdirp": "^3.0.1",
48
48
  "p-defer": "^3.0.0",
49
49
  "prexit": "0.0.5",
50
50
  "probot": "^12.2.4",
51
51
  "smee-client": "^1.2.3"
52
52
  },
53
53
  "devDependencies": {
54
- "@graphql-eslint/eslint-plugin": "^3.11.2",
54
+ "@graphql-eslint/eslint-plugin": "^3.20.1",
55
55
  "@octokit/graphql-schema": "^12.10.0",
56
56
  "@types/compression": "^1.7.2",
57
57
  "@types/express-session": "^1.17.4",
58
- "@types/mkdirp": "^1.0.2",
59
- "chai": "^4.3.6",
58
+ "chai": "^4.3.8",
60
59
  "graphql": "^16.6.0",
61
- "mocha": "^9.2.2",
60
+ "mocha": "^10.2.0",
62
61
  "nock": "^13.2.7",
63
62
  "nodemon": "^2.0.16",
64
63
  "npm-run-all": "^4.1.5",
65
- "sinon": "^12.0.1",
64
+ "sinon": "^16.0.0",
66
65
  "sinon-chai": "^3.7.0",
67
- "typescript": "^4.7.3"
66
+ "typescript": "^5.2.2"
68
67
  },
69
68
  "engines": {
70
- "node": "14.x || 16.x"
69
+ "node": ">= 16"
71
70
  },
72
71
  "nodemonConfig": {
73
72
  "exec": "node ./bin/wuffle",
@@ -92,5 +91,5 @@
92
91
  "index.js",
93
92
  "wuffle.config.example.js"
94
93
  ],
95
- "gitHead": "b0217a878f30b5cb1fe3dc1d25f3439e3490b450"
94
+ "gitHead": "e877cd1ef78c08ba2be44bac3473e00c03a27691"
96
95
  }
package/public/bundle.css CHANGED
@@ -1,18 +1,18 @@
1
1
  .icon.svelte-1og232h{vertical-align:initial}
2
- .hint-list.svelte-aelw4u.svelte-aelw4u{list-style:none;max-height:200px;overflow-y:auto;padding:0}.hint-list.svelte-aelw4u.svelte-aelw4u:not(:first-child){margin-top:0}.hint-list.svelte-aelw4u li.svelte-aelw4u{margin:0;padding:0.25rem 0.35rem;border-radius:5px}.hint-list.svelte-aelw4u li.selectable.svelte-aelw4u{cursor:pointer}.hint-list.svelte-aelw4u li.selectable.svelte-aelw4u:hover,.hint-list.svelte-aelw4u li.selectable.active.svelte-aelw4u{background:rgba(55, 172, 200, 0.1)}.matched.svelte-aelw4u.svelte-aelw4u{background:rgba(55, 172, 200, 0.2);color:#2c8aa0}
2
+ .hint-list.svelte-7refdd.svelte-7refdd{list-style:none;max-height:200px;overflow-y:auto;padding:0}.hint-list.svelte-7refdd.svelte-7refdd:not(:first-child){margin-top:0}.hint-list.svelte-7refdd li.svelte-7refdd{margin:0}.hint-list.svelte-7refdd li a.svelte-7refdd{padding:0.25rem 0.35rem;width:100%;display:block;border-radius:5px;color:inherit;text-decoration:none}.hint-list.svelte-7refdd li a.svelte-7refdd:hover,.hint-list.svelte-7refdd li a.active.svelte-7refdd{background:rgba(55, 172, 200, 0.1)}.matched.svelte-7refdd.svelte-7refdd{background:rgba(55, 172, 200, 0.2);color:#2c8aa0}
3
3
  .dropdown-parent.svelte-1g3cdmi.svelte-1g3cdmi{position:relative}.help-dropdown.svelte-1g3cdmi.svelte-1g3cdmi{border-radius:4px;margin:0;margin-top:5px;text-align:left;height:auto;position:relative;background:transparent;border:none;z-index:999;width:100%;min-width:0 !important;max-width:none !important;padding:0;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0, 0, 0, 0.1);box-shadow:0 0.1rem 1rem rgba(0, 0, 0, 0.075);position:absolute;top:100%;z-index:100;left:0px;right:auto;display:block}.help-dropdown.svelte-1g3cdmi .category.svelte-1g3cdmi{color:#37ACC8;font-weight:bold;margin:0.8rem;margin-bottom:0.25rem;font-size:1em}.help-dropdown.svelte-1g3cdmi .note.svelte-1g3cdmi{margin:0.8rem;color:#6c757d}.help-dropdown.svelte-1g3cdmi .note code.svelte-1g3cdmi{display:inline-block;padding:0 0.5rem;background:#F0F0F0;border-radius:4px}.board-filter.svelte-1g3cdmi.svelte-1g3cdmi{width:300px}.board-filter.expanded.svelte-1g3cdmi.svelte-1g3cdmi{width:500px;max-width:100%}.board-filter.svelte-1g3cdmi>input.svelte-1g3cdmi{width:100%}.icon.svelte-1g3cdmi.svelte-1g3cdmi{color:#dee2e6}
4
4
  .avatar.svelte-1ka4vk5.svelte-1ka4vk5{position:relative;display:inline-block;overflow:hidden;color:#fff;white-space:nowrap;text-align:center;vertical-align:middle;background:#ccc;width:32px;height:32px;line-height:32px}.avatar-shadow.svelte-1ka4vk5.svelte-1ka4vk5{position:absolute;top:0;left:0;width:100%;height:100%;box-shadow:inset 0 0 2px 0 rgba(0, 0, 0, 0.1)}.avatar-rounded.svelte-1ka4vk5.svelte-1ka4vk5{border-radius:50%}.avatar-rounded.svelte-1ka4vk5 .avatar-shadow.svelte-1ka4vk5{border-radius:50%}
5
5
  .loader.svelte-scyooh.svelte-scyooh{position:absolute;left:50%;top:50%;transform:translate(-50%, -50%);text-align:center;z-index:200;pointer-events:none}.loader.svelte-scyooh>.content.svelte-scyooh{opacity:0.3;transition:opacity 0.5s}.loader.shown.svelte-scyooh>.content.svelte-scyooh{opacity:1;animation:svelte-scyooh-pulsate 1s infinite;animation-timing-function:ease-in-out}.loader.svelte-scyooh:not(.shown)>.content.svelte-scyooh{opacity:0}@keyframes svelte-scyooh-pulsate{0%{transform:scale(1);opacity:1}50%{transform:scale(0.9);opacity:0.8}100%{transform:scale(1);opacity:1}}
6
6
  .powered-by.svelte-6ywnhs.svelte-6ywnhs.svelte-6ywnhs{position:absolute;bottom:10px;right:10px;padding:7px;border-radius:4px;opacity:0.5;transition:opacity 0.1s, background 0.1s;color:#333;z-index:10;align-items:center;display:flex}.powered-by.svelte-6ywnhs svg.svelte-6ywnhs.svelte-6ywnhs{vertical-align:bottom}.powered-by.svelte-6ywnhs:not(:hover) .logo.svelte-6ywnhs.svelte-6ywnhs{color:#999}.powered-by.svelte-6ywnhs.svelte-6ywnhs.svelte-6ywnhs:hover{opacity:1;box-shadow:0 1px 3px rgba(0, 0, 0, 0.3);background:white}.powered-by.svelte-6ywnhs:hover .help.svelte-6ywnhs.svelte-6ywnhs{display:block}.powered-by.svelte-6ywnhs .help.svelte-6ywnhs.svelte-6ywnhs{font-size:0.9em;display:none}.powered-by.svelte-6ywnhs .logo.svelte-6ywnhs.svelte-6ywnhs{margin-left:0.5em}.powered-by.svelte-6ywnhs .help-item.svelte-6ywnhs.svelte-6ywnhs{margin-left:0.5em}.powered-by.svelte-6ywnhs .help-item.svelte-6ywnhs+.help-item.svelte-6ywnhs{margin-left:1em}.powered-by.svelte-6ywnhs .help-item.svelte-6ywnhs.svelte-6ywnhs{display:inline-block}
7
7
  .notifications.svelte-14ytxa4{position:fixed;z-index:1010;top:24px;right:24px}
8
8
  .notification.svelte-eswexs{box-sizing:border-box;margin:0;padding:0;color:#6c757d;font-size:14px;font-variant:tabular-nums;line-height:1.5;list-style:none;width:384px;max-width:calc(100vw - 32px);padding:16px 24px;overflow:hidden;line-height:1.5;background:#fff;border-radius:3px;box-shadow:0 4px 12px rgba(0, 0, 0, 0.15);border-left:solid 4px #0dcaf0}.notification.error.svelte-eswexs{border-left-color:#dc3545}.notification.warning.svelte-eswexs{border-left-color:#ffc107}.heading.svelte-eswexs{color:#212529;font-weight:normal;font-size:1.2em;margin-bottom:5px}
9
- .tag.svelte-12ss6nn{list-style:none;display:inline-block;height:auto;margin:0 4px 4px 0;padding:2px 7px;font-size:12px;font-weight:400;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:white;background:#fafafa;border-radius:6px;text-decoration:none}.tag.svelte-12ss6nn:not(a){cursor:default}.tag.inverted.svelte-12ss6nn{color:#000}.svelte-12ss6nn:not(a.tag, .tag.clickable){cursor:default}
9
+ .tag.svelte-16zomaq{list-style:none;display:inline-block;height:auto;margin:0 4px 4px 0;padding:2px 7px;font-size:12px;font-weight:400;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:white;background:#fafafa;border-radius:6px;border:none;text-decoration:none}.tag.svelte-16zomaq:not(a){cursor:default}.tag.inverted.svelte-16zomaq{color:#000}.svelte-16zomaq:not(a.tag, .tag.clickable){cursor:default}
10
10
  .pull-request-icon.svelte-1vxuq5n{margin-right:3px}.pull-request-icon.open.svelte-1vxuq5n{color:#1a7f37}.pull-request-icon.closed.svelte-1vxuq5n{color:#cf222e}.pull-request-icon.merged.svelte-1vxuq5n{color:#8250df}.pull-request-icon.draft.svelte-1vxuq5n{color:#57606a}
11
11
  .icon.svelte-tuoxjm{margin-right:3px;color:#1d76db}
12
12
  .icon.svelte-1ek0gob{margin-right:3px}.icon.closed.svelte-1ek0gob{color:#8250df}.icon.open.svelte-1ek0gob{color:#1a7f37}.icon.not-planned.svelte-1ek0gob{color:#6e7781}
13
13
  .card-status.svelte-9jlwim.svelte-9jlwim{display:flex;flex-direction:row;align-items:stretch;height:3px;width:auto;margin:3px -8px -4px}.state.svelte-9jlwim.svelte-9jlwim{flex:1;background-color:#adb5bd}.state.svelte-9jlwim>span.svelte-9jlwim{display:none}.state.striped.svelte-9jlwim.svelte-9jlwim{background-image:linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);animation:svelte-9jlwim-progress-bar-stripes 1s linear infinite;background-size:1rem 1rem}.state.success.svelte-9jlwim.svelte-9jlwim{background-color:#4ede9b;box-shadow:0 1px 2px 0px rgba(36, 124, 83, 0.3)}.state.failure.svelte-9jlwim.svelte-9jlwim{background-color:#ea868f;box-shadow:0 1px 2px 0px rgba(203, 70, 83, 0.3)}.state.action-required.svelte-9jlwim.svelte-9jlwim{background-color:#ffda6a;box-shadow:0 1px 2px 0px rgba(230, 181, 32, 0.3)}.state.svelte-9jlwim+.state.svelte-9jlwim{margin-left:1px}@keyframes svelte-9jlwim-progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}
14
14
  .assignee.svelte-pr1826.svelte-pr1826{box-sizing:border-box;margin:0;font-size:14px;position:relative;display:flex;text-align:center;border-radius:2px;margin-left:3px;transition:margin 0.1s;height:18px}.assignee.svelte-pr1826 img.svelte-pr1826{height:100%;border-radius:2px;vertical-align:unset}.assignee.svelte-pr1826 .icon-shadow.svelte-pr1826{position:absolute;display:none;top:0;left:0;height:100%;width:100%;box-shadow:inset 0 0 2px 0 rgba(20, 20, 20, 0.3);border-radius:2px}.assignee.requested-reviewer.svelte-pr1826.svelte-pr1826:before{content:"";display:block;background:#bf8700;box-shadow:0 0 0 2px white;width:6px;height:6px;border-radius:50%;position:absolute;top:-2px;left:-2px;z-index:1}.assignee.commented.svelte-pr1826.svelte-pr1826:before{content:"";display:block;background:#0dcaf0;box-shadow:0 0 0 2px white;width:6px;height:6px;border-radius:50%;position:absolute;top:-2px;left:-2px;z-index:1}.assignee.approved.svelte-pr1826.svelte-pr1826:before{content:"";display:block;background:#198754;box-shadow:0 0 0 2px white;width:6px;height:6px;border-radius:50%;position:absolute;top:-2px;left:-2px;z-index:1}.assignee.requested-changes.svelte-pr1826.svelte-pr1826:before{content:"";display:block;background:#dc3545;box-shadow:0 0 0 2px white;width:6px;height:6px;border-radius:50%;position:absolute;top:-2px;left:-2px;z-index:1}.assignee.svelte-pr1826+.assignee.svelte-pr1826{margin-left:-6px;box-shadow:0 0 0 1px white}.hovered>.header .assignee+.assignee{margin-left:3px !important;box-shadow:none}
15
- .card-link:not(:last-child)>.card-status{margin-bottom:-2px !important}.board-card-links.attached .card-link:last-child>.card-status .state:last-child,.board-card>.card-status .state:last-child{border-bottom-right-radius:4px}.board-card-links.attached .card-link:last-child>.card-status .state:first-child,.board-card>.card-status .state:first-child{border-bottom-left-radius:4px}.header.svelte-1z10lc.svelte-1z10lc{display:flex;align-items:center;user-select:none}.header.svelte-1z10lc>.svelte-1z10lc{flex-shrink:0}.header.svelte-1z10lc>.collaborator-links.svelte-1z10lc{display:flex;align-items:center}.issue-number.svelte-1z10lc.svelte-1z10lc{font-weight:bold;margin-right:6px;display:flex;align-items:center;text-decoration:none}.short-title.svelte-1z10lc.svelte-1z10lc{color:#6c757d;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.card-link.svelte-1z10lc.svelte-1z10lc{border-top:solid 1px #F0F0F0;margin-top:2px;padding-top:2px}.card-link.svelte-1z10lc .short-title.svelte-1z10lc{flex:1}.card-link .epic{color:#1d76db}
16
- .board-card-container.svelte-dd5meo.svelte-dd5meo{width:100%}.board-card.svelte-dd5meo.svelte-dd5meo{background:white;border-radius:4px;box-shadow:0 1px 2px rgba(0, 0, 0, 0.2);position:relative;z-index:1;padding:4px 8px;cursor:default}.board-card.svelte-dd5meo .header.svelte-dd5meo{margin-bottom:7px}.card-link:not(:last-child)>.card-status{margin-bottom:-2px !important}.board-card-links.attached .card-link:last-child>.card-status .state:last-child,.board-card>.card-status .state:last-child{border-bottom-right-radius:4px}.board-card-links.attached .card-link:last-child>.card-status .state:first-child,.board-card>.card-status .state:first-child{border-bottom-left-radius:4px}.board-card-links.svelte-dd5meo.svelte-dd5meo{margin-top:2px}.header.svelte-dd5meo.svelte-dd5meo{display:flex;align-items:center;user-select:none}.header.svelte-dd5meo>.svelte-dd5meo{flex-shrink:0}.header.svelte-dd5meo>.repository.svelte-dd5meo{flex:1}.header.svelte-dd5meo>.collaborator-links.svelte-dd5meo{display:flex;align-items:center}.issue-type.svelte-dd5meo.svelte-dd5meo{margin-right:3px}.issue-type-pull-request.svelte-dd5meo.svelte-dd5meo{color:#6cc644}.issue-number.svelte-dd5meo.svelte-dd5meo{font-weight:bold;margin-right:6px;display:flex;align-items:center;text-decoration:none}.repository.svelte-dd5meo.svelte-dd5meo,.short-title.svelte-dd5meo.svelte-dd5meo{color:#6c757d;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.title.svelte-dd5meo.svelte-dd5meo{font-size:1.1em;margin:0 0 9px 0;min-height:30px;line-height:1.2em;color:#495057;overflow:hidden}.footer.svelte-dd5meo.svelte-dd5meo{display:flex;flex-direction:row;flex-wrap:wrap}.links.svelte-dd5meo.svelte-dd5meo{margin-left:auto}.links.svelte-dd5meo a.svelte-dd5meo{color:#adb5bd}.links.svelte-dd5meo a.svelte-dd5meo:hover{color:#6c757d}.tag.label,.tag.milestone{margin-right:4px;margin-bottom:4px}.tag.milestone{color:#343a40 !important;border:solid 1px #6c757d}.card-link:first-child{border-top:none !important;margin-top:1px !important}.board-card-links.attached.svelte-dd5meo.svelte-dd5meo{background:#F9F9F9;border-radius:0 0 4px 4px;box-shadow:inset 0 3px 5px -2px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.1);margin-top:-6px;position:relative;padding:7px 8px 4px 8px}.progress.svelte-dd5meo.svelte-dd5meo{display:flex;flex-direction:row;align-items:center;margin-bottom:7px;cursor:pointer}.progress.svelte-dd5meo svg.svelte-dd5meo{color:#6c757d}.progress.svelte-dd5meo .bar.svelte-dd5meo{border-radius:3px;height:5px;width:80px;background:#e9ecef;margin:auto 6px}.progress.svelte-dd5meo .bar .indicator.svelte-dd5meo{border-radius:3px;background:#6c757d;height:100%}.progress.svelte-dd5meo .text.svelte-dd5meo{margin-left:6px;font-size:0.9rem;color:#6c757d}
15
+ .card-link:not(:last-child)>.card-status{margin-bottom:-2px !important}.board-card-links.attached .card-link:last-child>.card-status .state:last-child,.board-card>.card-status .state:last-child{border-bottom-right-radius:4px}.board-card-links.attached .card-link:last-child>.card-status .state:first-child,.board-card>.card-status .state:first-child{border-bottom-left-radius:4px}.header.svelte-8rb8i7.svelte-8rb8i7{display:flex;align-items:center;user-select:none}.header.svelte-8rb8i7>.svelte-8rb8i7{flex-shrink:0}.header.svelte-8rb8i7>.collaborator-links.svelte-8rb8i7{display:flex;align-items:center}.issue-number.svelte-8rb8i7.svelte-8rb8i7{font-weight:bold;margin-right:6px;display:flex;align-items:center;text-decoration:none}.short-title.svelte-8rb8i7.svelte-8rb8i7{color:#6c757d;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.card-link.svelte-8rb8i7.svelte-8rb8i7{border-top:solid 1px #F0F0F0;margin-top:2px;padding-top:2px}.card-link.svelte-8rb8i7 .short-title.svelte-8rb8i7{flex:1}.card-link .epic{color:#1d76db}
16
+ .board-card-container.svelte-1mpimfa.svelte-1mpimfa{width:100%}.board-card.svelte-1mpimfa.svelte-1mpimfa{background:white;border-radius:4px;box-shadow:0 1px 2px rgba(0, 0, 0, 0.2);position:relative;z-index:1;padding:4px 8px;cursor:default;outline-width:3px}.board-card.svelte-1mpimfa .header.svelte-1mpimfa{margin-bottom:7px}.card-link:not(:last-child)>.card-status{margin-bottom:-2px !important}.board-card-links.attached .card-link:last-child>.card-status .state:last-child,.board-card>.card-status .state:last-child{border-bottom-right-radius:4px}.board-card-links.attached .card-link:last-child>.card-status .state:first-child,.board-card>.card-status .state:first-child{border-bottom-left-radius:4px}.board-card-links.svelte-1mpimfa.svelte-1mpimfa{margin-top:2px}.header.svelte-1mpimfa.svelte-1mpimfa{display:flex;align-items:center;user-select:none}.header.svelte-1mpimfa>.svelte-1mpimfa{flex-shrink:0}.header.svelte-1mpimfa>.repository.svelte-1mpimfa{flex:1}.header.svelte-1mpimfa>.collaborator-links.svelte-1mpimfa{display:flex;align-items:center}.issue-type.svelte-1mpimfa.svelte-1mpimfa{margin-right:3px}.issue-type-pull-request.svelte-1mpimfa.svelte-1mpimfa{color:#6cc644}.issue-number.svelte-1mpimfa.svelte-1mpimfa{font-weight:bold;margin-right:6px;display:flex;align-items:center;text-decoration:none}.repository.svelte-1mpimfa.svelte-1mpimfa,.short-title.svelte-1mpimfa.svelte-1mpimfa{color:#6c757d;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.title.svelte-1mpimfa.svelte-1mpimfa{font-size:1.1em;margin:0 0 9px 0;min-height:30px;line-height:1.2em;color:#495057;overflow:hidden}.footer.svelte-1mpimfa.svelte-1mpimfa{display:flex;flex-direction:row;flex-wrap:wrap}.links.svelte-1mpimfa.svelte-1mpimfa{margin-left:auto}.links.svelte-1mpimfa a.svelte-1mpimfa{color:#adb5bd}.links.svelte-1mpimfa a.svelte-1mpimfa:hover{color:#6c757d}.tag.label,.tag.milestone{margin-right:4px;margin-bottom:4px}.tag.milestone{color:#343a40 !important;border:solid 1px #6c757d}.card-link:first-child{border-top:none !important;margin-top:1px !important}.board-card-links.attached.svelte-1mpimfa.svelte-1mpimfa{background:#F9F9F9;border-radius:0 0 4px 4px;box-shadow:inset 0 3px 5px -2px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.1);margin-top:-6px;position:relative;padding:7px 8px 4px 8px}.progress.svelte-1mpimfa.svelte-1mpimfa{display:flex;flex-direction:row;align-items:center;margin-bottom:7px;padding:0;cursor:pointer;text-decoration:none}.progress.svelte-1mpimfa svg.svelte-1mpimfa{color:#6c757d}.progress.svelte-1mpimfa .bar.svelte-1mpimfa{border-radius:3px;height:5px;width:80px;background:#e9ecef;margin:auto 6px}.progress.svelte-1mpimfa .bar .indicator.svelte-1mpimfa{border-radius:3px;background:#6c757d;height:100%}.progress.svelte-1mpimfa .text.svelte-1mpimfa{margin-left:6px;font-size:0.9rem;color:#6c757d}
17
17
  .dropdown-parent.svelte-w96e7f{position:relative}.help-dropdown.svelte-w96e7f{border-radius:4px;margin:0;margin-top:5px;text-align:left;height:auto;position:relative;background:transparent;border:none;z-index:999;width:100%;min-width:0 !important;max-width:none !important;padding:0;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0, 0, 0, 0.1);box-shadow:0 0.1rem 1rem rgba(0, 0, 0, 0.075);position:absolute;top:100%;z-index:100;left:0px;right:auto;display:block}.repository-select.svelte-w96e7f{position:fixed;top:0;left:0;right:0;bottom:0;z-index:10}.overlay.svelte-w96e7f{width:100%;height:100%;background:rgba(30, 30, 30, 0.3)}.issue-creator.svelte-w96e7f{position:absolute;z-index:2;width:500px;max-width:100%;background:white;top:30%;left:50%;transform:translate(-50%);line-height:1.5;border-radius:5px;box-shadow:0 4px 12px rgba(0, 0, 0, 0.15)}
18
18
  .taskboard.svelte-1i4u2uq.svelte-1i4u2uq{height:100vh;display:flex;flex-direction:column}@media all and (max-width: 600px){.board-filter{width:100% !important}.navbar .board-filter-parent{flex:1 !important}.navbar .logo{width:32px;height:32px}}.taskboard-error.svelte-1i4u2uq.svelte-1i4u2uq{position:absolute;top:50%;left:50%;transform:translate(-50%, -50%);text-align:center}.taskboard-error.svelte-1i4u2uq p.svelte-1i4u2uq{font-size:1.3em;margin-top:1.7rem;margin-bottom:3rem;color:#495057}.taskboard-board.svelte-1i4u2uq.svelte-1i4u2uq{--container-gap:.5rem;display:flex;flex:1;overflow-x:auto;margin-top:0;gap:var(--container-gap)}.taskboard-column.svelte-1i4u2uq.svelte-1i4u2uq{display:flex;flex-direction:column;min-width:250px;flex:1;border-radius:0.25rem;background:#ebecf0;--container-gap:.7rem}.taskboard-column.collapsed.svelte-1i4u2uq.svelte-1i4u2uq{min-width:3rem;flex:0}.taskboard-column-items.svelte-1i4u2uq.svelte-1i4u2uq{flex:1;overflow-y:auto;margin-top:0}.taskboard-column-header.svelte-1i4u2uq.svelte-1i4u2uq{text-align:center;line-height:2.4em;font-size:1.25em;color:inherit}.taskboard-column-collapse.svelte-1i4u2uq.svelte-1i4u2uq{color:#adb5bd;font-size:1.2rem}.taskboard-column-collapse.svelte-1i4u2uq.svelte-1i4u2uq:hover{color:#495057}.taskboard-column.svelte-1i4u2uq:not(.collapsed) .taskboard-column-header.svelte-1i4u2uq{position:relative}.taskboard-column.svelte-1i4u2uq:not(.collapsed) .taskboard-column-collapse.svelte-1i4u2uq{position:absolute;padding:0 0.4rem;top:50%;left:0.5rem;transform:translateY(-50%)}.taskboard-column.collapsed.svelte-1i4u2uq .taskboard-column-collapse.svelte-1i4u2uq{padding:0 0.1rem;margin:0.6rem 0.5rem}.taskboard-column.collapsed.svelte-1i4u2uq .taskboard-column-header.svelte-1i4u2uq{display:flex;flex-direction:column;flex:1}.taskboard-column.collapsed.svelte-1i4u2uq .taskboard-column-name.svelte-1i4u2uq,.taskboard-column.collapsed.svelte-1i4u2uq .taskboard-column-issue-count.svelte-1i4u2uq{transform:rotate(-180deg);writing-mode:vertical-rl}.taskboard-column.collapsed.svelte-1i4u2uq .taskboard-column-name.svelte-1i4u2uq{order:2}.taskboard-column.collapsed.svelte-1i4u2uq .taskboard-column-issue-count.svelte-1i4u2uq{padding:0.5em 0;order:0}.taskboard-column-name.svelte-1i4u2uq.svelte-1i4u2uq{color:#424657}.taskboard-column-issue-count.svelte-1i4u2uq.svelte-1i4u2uq{color:#37ACC8;display:inline-block;padding:0 0.25em}.card-container.svelte-1i4u2uq+.card-container.svelte-1i4u2uq{margin-top:var(--container-gap)}.taskboard.svelte-1i4u2uq.svelte-1i4u2uq{position:relative}