@punch-in/strapi-admin 1.2.15 → 1.2.17

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.
Files changed (36) hide show
  1. package/admin/src/components/GlobalStyle/index.js +19 -0
  2. package/admin/src/components/LeftMenu/LeftMenuLinkHeader/Title.js +1 -0
  3. package/admin/src/components/LeftMenu/LeftMenuLinkSection/LeftMenuListLink.js +8 -1
  4. package/admin/src/components/LeftMenu/LinksContainer/index.js +2 -0
  5. package/admin/src/containers/HomePage/PunchInToday.js +1 -40
  6. package/admin/src/containers/HomePage/RollCall.js +355 -0
  7. package/admin/src/containers/HomePage/VisitorApprovals.js +295 -0
  8. package/admin/src/containers/HomePage/components.js +122 -1
  9. package/admin/src/containers/HomePage/index.js +4 -0
  10. package/admin/src/containers/HomePage/punchUtils.js +42 -0
  11. package/admin/src/containers/LocaleToggle/Wrapper.js +4 -0
  12. package/admin/src/translations/en.json +18 -1
  13. package/package.json +1 -1
  14. package/strapi-admin/node_modules/is-wsl/index.d.ts +0 -15
  15. package/strapi-admin/node_modules/is-wsl/index.js +0 -31
  16. package/strapi-admin/node_modules/is-wsl/license +0 -9
  17. package/strapi-admin/node_modules/is-wsl/package.json +0 -77
  18. package/strapi-admin/node_modules/is-wsl/readme.md +0 -36
  19. package/strapi-admin/node_modules/qs/.editorconfig +0 -39
  20. package/strapi-admin/node_modules/qs/.eslintignore +0 -2
  21. package/strapi-admin/node_modules/qs/.eslintrc +0 -35
  22. package/strapi-admin/node_modules/qs/.github/FUNDING.yml +0 -12
  23. package/strapi-admin/node_modules/qs/.nycrc +0 -13
  24. package/strapi-admin/node_modules/qs/CHANGELOG.md +0 -372
  25. package/strapi-admin/node_modules/qs/LICENSE.md +0 -29
  26. package/strapi-admin/node_modules/qs/README.md +0 -611
  27. package/strapi-admin/node_modules/qs/dist/qs.js +0 -1903
  28. package/strapi-admin/node_modules/qs/lib/formats.js +0 -23
  29. package/strapi-admin/node_modules/qs/lib/index.js +0 -11
  30. package/strapi-admin/node_modules/qs/lib/parse.js +0 -263
  31. package/strapi-admin/node_modules/qs/lib/stringify.js +0 -290
  32. package/strapi-admin/node_modules/qs/lib/utils.js +0 -251
  33. package/strapi-admin/node_modules/qs/package.json +0 -100
  34. package/strapi-admin/node_modules/qs/test/parse.js +0 -781
  35. package/strapi-admin/node_modules/qs/test/stringify.js +0 -848
  36. package/strapi-admin/node_modules/qs/test/utils.js +0 -136
@@ -0,0 +1,295 @@
1
+ import React, { useCallback, useEffect, useState } from 'react';
2
+ import styled from 'styled-components';
3
+ import { FormattedMessage } from 'react-intl';
4
+ import { request } from 'strapi-helper-plugin';
5
+ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
6
+ import { faIdBadge, faCheck, faTimes, faSyncAlt } from '@fortawesome/free-solid-svg-icons';
7
+ import moment from 'moment';
8
+ import {
9
+ Block,
10
+ PunchList,
11
+ PunchRow,
12
+ PunchMeta,
13
+ PunchName,
14
+ PunchTimes,
15
+ PunchAction,
16
+ EmptyPunch,
17
+ RollCallHeader,
18
+ RefreshBtn,
19
+ ApproveBtn,
20
+ } from './components';
21
+
22
+ // Pending visitor sign-in requests (see features/VISITOR-SIGN-IN.md), so an
23
+ // administrator can approve or reject without opening the content manager.
24
+ // Approving/rejecting goes through the same PUT /visitor-requests/:id the
25
+ // content manager uses, so the Visitor user is created, the decision is
26
+ // recorded and the visitor-notifications row is written exactly as before.
27
+ //
28
+ // Always rendered (with an empty state) so it is clear the feature is there
29
+ // even when no visitor has registered yet.
30
+
31
+ const REFRESH_MS = 60 * 1000;
32
+
33
+ const Left = styled.div`
34
+ display: flex;
35
+ align-items: center;
36
+ gap: 14px;
37
+ min-width: 0;
38
+ `;
39
+
40
+ const Photo = styled.div`
41
+ flex: 0 0 auto;
42
+ width: 52px;
43
+ height: 52px;
44
+ border-radius: 50%;
45
+ background: #e9edf5 center / cover no-repeat;
46
+ border: 2px solid #ffffff;
47
+ box-shadow: 0 0 0 1px #e3e9f3;
48
+ display: flex;
49
+ align-items: center;
50
+ justify-content: center;
51
+ color: #8e8ea9;
52
+ font-size: 18px;
53
+ `;
54
+
55
+ const Purpose = styled.div`
56
+ margin-top: 3px;
57
+ font-size: 13px;
58
+ color: #5c5f66;
59
+ max-width: 520px;
60
+ overflow: hidden;
61
+ text-overflow: ellipsis;
62
+ white-space: nowrap;
63
+ `;
64
+
65
+ const Count = styled.span`
66
+ display: inline-block;
67
+ margin-left: 10px;
68
+ padding: 0 9px;
69
+ border-radius: 10px;
70
+ background: #fff4e5;
71
+ color: #b25e00;
72
+ font-size: 13px;
73
+ font-weight: 700;
74
+ line-height: 20px;
75
+ vertical-align: middle;
76
+ `;
77
+
78
+ const Actions = styled(PunchAction)`
79
+ display: flex;
80
+ align-items: center;
81
+ gap: 8px;
82
+ `;
83
+
84
+ const RejectBtn = styled.button`
85
+ display: inline-flex;
86
+ align-items: center;
87
+ gap: 6px;
88
+ height: 32px;
89
+ padding: 0 12px;
90
+ border: 1px solid #f5c6c6;
91
+ border-radius: 4px;
92
+ background: #ffffff;
93
+ color: #d02b20;
94
+ font-size: 13px;
95
+ font-weight: 600;
96
+ cursor: pointer;
97
+
98
+ &:hover:not(:disabled) {
99
+ background: #fdecec;
100
+ }
101
+ &:disabled {
102
+ opacity: 0.6;
103
+ cursor: default;
104
+ }
105
+ `;
106
+
107
+ const NoteInput = styled.input`
108
+ height: 32px;
109
+ width: 220px;
110
+ padding: 0 10px;
111
+ border: 1px solid #e3e9f3;
112
+ border-radius: 4px;
113
+ font-size: 13px;
114
+ `;
115
+
116
+ const ErrorText = styled(EmptyPunch)`
117
+ color: #d02b20;
118
+ `;
119
+
120
+ const mediaUrl = (url) => {
121
+ if (!url) return null;
122
+ if (/^(https?:)?\/\//.test(url)) return url;
123
+ const base = (window.strapi && window.strapi.backendURL) || '';
124
+ return `${String(base).replace(/\/$/, '')}${url}`;
125
+ };
126
+
127
+ const photoOf = (visit) => {
128
+ const file = Array.isArray(visit.photo) ? visit.photo[0] : visit.photo;
129
+ if (!file) return null;
130
+ return mediaUrl((file.formats && file.formats.thumbnail && file.formats.thumbnail.url) || file.url);
131
+ };
132
+
133
+ const visitLabel = (visit) => {
134
+ const start = moment(visit.visitStart);
135
+ const end = visit.validUntil ? moment(visit.validUntil) : null;
136
+ if (!start.isValid()) return '—';
137
+ const from = start.format('ddd D MMM, HH:mm');
138
+ return end && end.isValid() ? `${from} → valid until ${end.format('ddd D MMM, HH:mm')}` : from;
139
+ };
140
+
141
+ const VisitorApprovals = () => {
142
+ const [requests, setRequests] = useState([]);
143
+ const [loaded, setLoaded] = useState(false);
144
+ const [loading, setLoading] = useState(false);
145
+ const [error, setError] = useState(null);
146
+ const [busyId, setBusyId] = useState(null);
147
+ const [rejectingId, setRejectingId] = useState(null);
148
+ const [note, setNote] = useState('');
149
+
150
+ const load = useCallback(async () => {
151
+ setLoading(true);
152
+ try {
153
+ const list = await request('/visitor-requests?status=pending&_sort=visitStart:ASC&_limit=-1', {
154
+ method: 'GET',
155
+ });
156
+ setRequests(Array.isArray(list) ? list : []);
157
+ setError(null);
158
+ } catch (err) {
159
+ setError('Could not load visitor requests.');
160
+ } finally {
161
+ setLoading(false);
162
+ setLoaded(true);
163
+ }
164
+ }, []);
165
+
166
+ useEffect(() => {
167
+ load();
168
+ const timer = setInterval(load, REFRESH_MS);
169
+ return () => clearInterval(timer);
170
+ }, [load]);
171
+
172
+ const decide = async (visit, status, decisionNote) => {
173
+ setBusyId(visit.id);
174
+ setError(null);
175
+ try {
176
+ const body = { status };
177
+ if (decisionNote) body.decisionNote = decisionNote;
178
+ await request(`/visitor-requests/${visit.id}`, { method: 'PUT', body });
179
+ setRequests((prev) => prev.filter((r) => r.id !== visit.id));
180
+ setRejectingId(null);
181
+ setNote('');
182
+ } catch (err) {
183
+ setError(`Could not ${status === 'approved' ? 'approve' : 'reject'} ${visit.firstName} ${visit.lastName}. Please try again.`);
184
+ } finally {
185
+ setBusyId(null);
186
+ }
187
+ };
188
+
189
+ if (!loaded) {
190
+ return null;
191
+ }
192
+
193
+ return (
194
+ <Block>
195
+ <RollCallHeader>
196
+ <div>
197
+ <h2>
198
+ <FontAwesomeIcon icon={faIdBadge} style={{ marginRight: 10 }} />
199
+ <FormattedMessage id="HomePage.visitorApprovals.title" defaultMessage="Visitor approval requests" />
200
+ <Count>{requests.length}</Count>
201
+ </h2>
202
+ <p style={{ marginTop: 8, color: '#5c5f66', fontSize: 14 }}>
203
+ <FormattedMessage
204
+ id="HomePage.visitorApprovals.subtitle"
205
+ defaultMessage="Check the photo is clear before approving: it is used for face recognition on the tablet."
206
+ />
207
+ </p>
208
+ </div>
209
+ <RefreshBtn type="button" onClick={load} disabled={loading}>
210
+ <FontAwesomeIcon icon={faSyncAlt} spin={loading} />
211
+ <FormattedMessage id="HomePage.visitorApprovals.refresh" defaultMessage="Refresh" />
212
+ </RefreshBtn>
213
+ </RollCallHeader>
214
+
215
+ {error && <ErrorText>{error}</ErrorText>}
216
+
217
+ {!requests.length && !error && (
218
+ <EmptyPunch>
219
+ <FormattedMessage
220
+ id="HomePage.visitorApprovals.empty"
221
+ defaultMessage="No pending visitor requests."
222
+ />
223
+ </EmptyPunch>
224
+ )}
225
+
226
+ <PunchList style={{ maxHeight: 520 }}>
227
+ {requests.map((visit) => {
228
+ const photo = photoOf(visit);
229
+ const busy = busyId === visit.id;
230
+ const rejecting = rejectingId === visit.id;
231
+ return (
232
+ <PunchRow key={visit.id}>
233
+ <Left>
234
+ <Photo style={photo ? { backgroundImage: `url("${photo}")` } : undefined}>
235
+ {!photo && <FontAwesomeIcon icon={faIdBadge} />}
236
+ </Photo>
237
+ <PunchMeta>
238
+ <PunchName>
239
+ {visit.firstName} {visit.lastName}
240
+ </PunchName>
241
+ <PunchTimes>
242
+ <span>{visit.email}</span>
243
+ <span>{visitLabel(visit)}</span>
244
+ </PunchTimes>
245
+ <Purpose title={visit.purpose}>{visit.purpose}</Purpose>
246
+ </PunchMeta>
247
+ </Left>
248
+ <Actions>
249
+ {rejecting ? (
250
+ <>
251
+ <NoteInput
252
+ autoFocus
253
+ placeholder="Reason (optional)"
254
+ value={note}
255
+ maxLength={250}
256
+ onChange={(e) => setNote(e.target.value)}
257
+ onKeyDown={(e) => {
258
+ if (e.key === 'Enter') decide(visit, 'rejected', note.trim());
259
+ if (e.key === 'Escape') setRejectingId(null);
260
+ }}
261
+ />
262
+ <RejectBtn type="button" disabled={busy} onClick={() => decide(visit, 'rejected', note.trim())}>
263
+ <FontAwesomeIcon icon={faTimes} /> Confirm reject
264
+ </RejectBtn>
265
+ <RefreshBtn type="button" onClick={() => setRejectingId(null)}>
266
+ Cancel
267
+ </RefreshBtn>
268
+ </>
269
+ ) : (
270
+ <>
271
+ <RejectBtn
272
+ type="button"
273
+ disabled={busy}
274
+ onClick={() => {
275
+ setRejectingId(visit.id);
276
+ setNote('');
277
+ }}
278
+ >
279
+ <FontAwesomeIcon icon={faTimes} /> Reject
280
+ </RejectBtn>
281
+ <ApproveBtn type="button" disabled={busy} onClick={() => decide(visit, 'approved')}>
282
+ <FontAwesomeIcon icon={faCheck} /> {busy ? 'Approving…' : 'Approve'}
283
+ </ApproveBtn>
284
+ </>
285
+ )}
286
+ </Actions>
287
+ </PunchRow>
288
+ );
289
+ })}
290
+ </PunchList>
291
+ </Block>
292
+ );
293
+ };
294
+
295
+ export default VisitorApprovals;
@@ -415,4 +415,125 @@ const ApproveBtn = styled.button`
415
415
  }
416
416
  `;
417
417
 
418
- export { ALink, Block, Container, LinkWrapper, P, Separator, SocialLinkWrapper, Wave, SiteStrip, SiteTab, SiteNav, SiteNavBtn, PunchList, PunchRow, PunchMeta, PunchName, PunchTimes, PunchAction, EmptyPunch, StatusPill, ApproveBtn };
418
+ // Site roll call (RollCall.js) - the safety/security officer's quick view of
419
+ // who is on site. Red so it's findable at a glance in an emergency.
420
+ const RollCallButton = styled.button`
421
+ display: inline-flex;
422
+ align-items: center;
423
+ gap: 10px;
424
+ height: 44px;
425
+ padding: 0 20px;
426
+ margin-bottom: 18px;
427
+ border: none;
428
+ border-radius: 4px;
429
+ background: ${props => (props.$open ? '#9b1c13' : '#d63a2f')};
430
+ color: #ffffff;
431
+ font-size: 15px;
432
+ font-weight: 700;
433
+ cursor: pointer;
434
+ box-shadow: 0 2px 4px 0 #e3e9f3;
435
+
436
+ &:hover {
437
+ background: #b52d23;
438
+ }
439
+ `;
440
+
441
+ const RollCallHeader = styled.div`
442
+ display: flex;
443
+ align-items: flex-start;
444
+ justify-content: space-between;
445
+ gap: 12px;
446
+ flex-wrap: wrap;
447
+ `;
448
+
449
+ const RollCallSummary = styled.p`
450
+ display: flex;
451
+ gap: 16px;
452
+ flex-wrap: wrap;
453
+ margin: 8px 0 16px;
454
+ font-size: 14px;
455
+ color: #5c5f66;
456
+
457
+ b {
458
+ color: #333740;
459
+ }
460
+ `;
461
+
462
+ const RefreshBtn = styled.button`
463
+ display: inline-flex;
464
+ align-items: center;
465
+ gap: 6px;
466
+ height: 32px;
467
+ padding: 0 12px;
468
+ border: 1px solid #e3e9f3;
469
+ border-radius: 4px;
470
+ background: #ffffff;
471
+ color: #007eff;
472
+ font-size: 13px;
473
+ font-weight: 600;
474
+ cursor: pointer;
475
+
476
+ &:disabled {
477
+ opacity: 0.6;
478
+ cursor: default;
479
+ }
480
+ `;
481
+
482
+ const VisitorBadge = styled.span`
483
+ display: inline-block;
484
+ margin-left: 8px;
485
+ padding: 0 7px;
486
+ border-radius: 9px;
487
+ background: #fff4e5;
488
+ color: #b25e00;
489
+ font-size: 11px;
490
+ font-weight: 700;
491
+ line-height: 18px;
492
+ vertical-align: middle;
493
+ `;
494
+
495
+ const CheckToggle = styled.label`
496
+ display: inline-flex;
497
+ align-items: center;
498
+ gap: 8px;
499
+ margin: 0;
500
+ font-size: 13px;
501
+ font-weight: 600;
502
+ color: #333740;
503
+ cursor: pointer;
504
+ user-select: none;
505
+
506
+ input {
507
+ width: 18px;
508
+ height: 18px;
509
+ margin: 0;
510
+ cursor: pointer;
511
+ }
512
+ `;
513
+
514
+ const CheckedTag = styled.span`
515
+ display: inline-flex;
516
+ align-items: center;
517
+ gap: 6px;
518
+ height: 28px;
519
+ padding: 0 10px;
520
+ border-radius: 14px;
521
+ background: #eafbe7;
522
+ color: #27b97c;
523
+ font-size: 13px;
524
+ font-weight: 700;
525
+ `;
526
+
527
+ const UndoBtn = styled.button`
528
+ margin-left: 10px;
529
+ padding: 0;
530
+ border: none;
531
+ background: none;
532
+ color: #007eff;
533
+ font-size: 13px;
534
+ font-weight: 600;
535
+ text-decoration: underline;
536
+ cursor: pointer;
537
+ `;
538
+
539
+ export { ALink, Block, Container, LinkWrapper, P, Separator, SocialLinkWrapper, Wave, SiteStrip, SiteTab, SiteNav, SiteNavBtn, PunchList, PunchRow, PunchMeta, PunchName, PunchTimes, PunchAction, EmptyPunch, StatusPill, ApproveBtn, RollCallButton, RollCallHeader, RollCallSummary, RefreshBtn, VisitorBadge, CheckToggle, CheckedTag, UndoBtn };
@@ -15,6 +15,8 @@ import useFetch from './hooks';
15
15
  import { ALink, Block, Container, LinkWrapper, P, Wave, Separator } from './components';
16
16
  import SocialLink from './SocialLink';
17
17
  import PunchInToday from './PunchInToday';
18
+ import RollCall from './RollCall';
19
+ import VisitorApprovals from './VisitorApprovals';
18
20
 
19
21
  const FIRST_BLOCK_LINKS = [
20
22
  {
@@ -89,6 +91,8 @@ const HomePage = ({ history: { push } }) => {
89
91
  <Container className="container-fluid">
90
92
  <div className="row">
91
93
  <div className="col-12">
94
+ <RollCall />
95
+ <VisitorApprovals />
92
96
  <PunchInToday />
93
97
  </div>
94
98
  </div>
@@ -0,0 +1,42 @@
1
+ import moment from 'moment';
2
+
3
+ // Shared by the home page's time-sheet panels (PunchInToday, RollCall).
4
+
5
+ export const NONE_SITE = 'none';
6
+
7
+ export const displayName = (user) => {
8
+ if (!user) {
9
+ return 'Unknown employee';
10
+ }
11
+ const last = user.lastName || '';
12
+ const first = user.firstName || '';
13
+ if (last && first) {
14
+ return last + ', ' + first;
15
+ }
16
+ return last || first || user.email || user.username || 'Employee';
17
+ };
18
+
19
+ export const clockLabel = (value) => {
20
+ if (!value) {
21
+ return null;
22
+ }
23
+ const parsed = moment(value);
24
+ return parsed.isValid() ? parsed.format('HH:mm') : null;
25
+ };
26
+
27
+ export const siteIdOf = (site) => {
28
+ if (!site) {
29
+ return NONE_SITE;
30
+ }
31
+ if (typeof site === 'object') {
32
+ return site.id != null ? String(site.id) : NONE_SITE;
33
+ }
34
+ return String(site);
35
+ };
36
+
37
+ export const siteNameOf = (site) => {
38
+ if (site && typeof site === 'object' && site.name) {
39
+ return site.name;
40
+ }
41
+ return 'No site';
42
+ };
@@ -48,6 +48,10 @@ const Wrapper = styled.div`
48
48
  letter-spacing: 0.5;
49
49
  vertical-align: baseline;
50
50
  }
51
+
52
+ &:hover span {
53
+ color: rgb(247, 91, 29);
54
+ }
51
55
  }
52
56
 
53
57
  .localeDropdownMenu {
@@ -54,13 +54,30 @@
54
54
  "HomePage.community": "Join Punch-in Community",
55
55
  "HomePage.greetings": "Hi {name}!",
56
56
  "HomePage.helmet.title": "Homepage",
57
- "HomePage.punchIn.title": "Attendance recorded",
57
+ "HomePage.punchIn.title": "Attendance today",
58
58
  "HomePage.punchIn.subtitle": "{count} {count, plural, one {person} other {people}} clocked in · grouped by site",
59
59
  "HomePage.punchIn.loading": "Loading today's punch-ins…",
60
60
  "HomePage.punchIn.empty": "No one has punched in yet today.",
61
61
  "HomePage.punchIn.noneAtSite": "No one has punched in at this site today.",
62
62
  "HomePage.punchIn.approved": "Time approved",
63
63
  "HomePage.punchIn.approveError": "Could not approve this time-sheet",
64
+ "HomePage.rollCall.button": "Site roll call",
65
+ "HomePage.rollCall.hide": "Hide site roll call",
66
+ "HomePage.rollCall.title": "Site roll call",
67
+ "HomePage.rollCall.subtitle": "Everyone clocked in, including visitors, plus anyone who clocked out in the last hour.",
68
+ "HomePage.rollCall.refresh": "Refresh",
69
+ "HomePage.rollCall.updated": "Updated {time}",
70
+ "HomePage.rollCall.loading": "Loading roll call…",
71
+ "HomePage.rollCall.onSite": "{count} on site",
72
+ "HomePage.rollCall.left": "{count} left in the last hour",
73
+ "HomePage.rollCall.checkedCount": "{checked} of {total} checked",
74
+ "HomePage.rollCall.allSites": "All sites",
75
+ "HomePage.rollCall.empty": "No one is clocked in, and no one has clocked out in the last hour.",
76
+ "HomePage.rollCall.visitor": "Visitor",
77
+ "HomePage.rollCall.leftAt": "Left at {time}",
78
+ "HomePage.rollCall.stillOnSite": "On site",
79
+ "HomePage.rollCall.checked": "Checked",
80
+ "HomePage.rollCall.undo": "Undo",
64
81
  "HomePage.roadmap": "See our roadmap",
65
82
  "HomePage.welcome.congrats": "Congrats!",
66
83
  "HomePage.welcome.congrats.content": "You are logged in as the first administrator. To discover the powerful features provided by Punch-in,",
package/package.json CHANGED
@@ -139,5 +139,5 @@
139
139
  "develop:ce": "STRAPI_DISABLE_EE=true webpack-dev-server --config webpack.config.dev.js",
140
140
  "test": "echo \"no tests yet\""
141
141
  },
142
- "version": "1.2.15"
142
+ "version": "1.2.17"
143
143
  }
@@ -1,15 +0,0 @@
1
- /**
2
- Check if the process is running inside [Windows Subsystem for Linux](https://msdn.microsoft.com/commandline/wsl/about) (Bash on Windows).
3
-
4
- @example
5
- ```
6
- import isWsl = require('is-wsl');
7
-
8
- // When running inside Windows Subsystem for Linux
9
- console.log(isWsl);
10
- //=> true
11
- ```
12
- */
13
- declare const isWsl: boolean;
14
-
15
- export = isWsl;
@@ -1,31 +0,0 @@
1
- 'use strict';
2
- const os = require('os');
3
- const fs = require('fs');
4
- const isDocker = require('is-docker');
5
-
6
- const isWsl = () => {
7
- if (process.platform !== 'linux') {
8
- return false;
9
- }
10
-
11
- if (os.release().toLowerCase().includes('microsoft')) {
12
- if (isDocker()) {
13
- return false;
14
- }
15
-
16
- return true;
17
- }
18
-
19
- try {
20
- return fs.readFileSync('/proc/version', 'utf8').toLowerCase().includes('microsoft') ?
21
- !isDocker() : false;
22
- } catch (_) {
23
- return false;
24
- }
25
- };
26
-
27
- if (process.env.__IS_WSL_TEST__) {
28
- module.exports = isWsl;
29
- } else {
30
- module.exports = isWsl();
31
- }
@@ -1,9 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
-
7
- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
-
9
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -1,77 +0,0 @@
1
- {
2
- "_from": "is-wsl@^2.0.0",
3
- "_id": "is-wsl@2.2.0",
4
- "_inBundle": false,
5
- "_integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
6
- "_location": "/@punch-in/strapi-admin/is-wsl",
7
- "_phantomChildren": {},
8
- "_requested": {
9
- "type": "range",
10
- "registry": true,
11
- "raw": "is-wsl@^2.0.0",
12
- "name": "is-wsl",
13
- "escapedName": "is-wsl",
14
- "rawSpec": "^2.0.0",
15
- "saveSpec": null,
16
- "fetchSpec": "^2.0.0"
17
- },
18
- "_requiredBy": [
19
- "/@punch-in/strapi-admin"
20
- ],
21
- "_resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
22
- "_shasum": "74a4c76e77ca9fd3f932f290c17ea326cd157271",
23
- "_spec": "is-wsl@^2.0.0",
24
- "_where": "/webapps/strapiProject/3.6.8/defaultProject/node_modules/@punch-in/strapi-admin",
25
- "author": {
26
- "name": "Sindre Sorhus",
27
- "email": "sindresorhus@gmail.com",
28
- "url": "sindresorhus.com"
29
- },
30
- "bugs": {
31
- "url": "https://github.com/sindresorhus/is-wsl/issues"
32
- },
33
- "bundleDependencies": false,
34
- "dependencies": {
35
- "is-docker": "^2.0.0"
36
- },
37
- "deprecated": false,
38
- "description": "Check if the process is running inside Windows Subsystem for Linux (Bash on Windows)",
39
- "devDependencies": {
40
- "ava": "^1.4.1",
41
- "clear-module": "^3.2.0",
42
- "proxyquire": "^2.1.0",
43
- "tsd": "^0.7.2",
44
- "xo": "^0.24.0"
45
- },
46
- "engines": {
47
- "node": ">=8"
48
- },
49
- "files": [
50
- "index.js",
51
- "index.d.ts"
52
- ],
53
- "homepage": "https://github.com/sindresorhus/is-wsl#readme",
54
- "keywords": [
55
- "check",
56
- "wsl",
57
- "windows",
58
- "subsystem",
59
- "linux",
60
- "detect",
61
- "bash",
62
- "process",
63
- "console",
64
- "terminal",
65
- "is"
66
- ],
67
- "license": "MIT",
68
- "name": "is-wsl",
69
- "repository": {
70
- "type": "git",
71
- "url": "git+https://github.com/sindresorhus/is-wsl.git"
72
- },
73
- "scripts": {
74
- "test": "xo && ava && tsd"
75
- },
76
- "version": "2.2.0"
77
- }