@striae-org/striae 5.2.1 → 5.3.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/.env.example +2 -10
- package/README.md +5 -46
- package/app/components/actions/case-export/core-export.ts +2 -174
- package/app/components/actions/case-export/download-handlers.ts +83 -750
- package/app/components/actions/case-export/index.ts +6 -30
- package/app/components/actions/case-export/metadata-helpers.ts +0 -78
- package/app/components/actions/case-export/types-constants.ts +0 -43
- package/app/components/actions/case-import/confirmation-import.ts +13 -14
- package/app/components/actions/case-import/zip-processing.ts +92 -12
- package/app/components/actions/generate-pdf.ts +3 -2
- package/app/components/audit/user-audit-viewer.tsx +0 -19
- package/app/components/audit/viewer/audit-viewer-header.tsx +0 -33
- package/app/components/navbar/case-modals/archive-case-modal.tsx +1 -1
- package/app/components/navbar/navbar.tsx +1 -1
- package/app/components/sidebar/case-import/case-import.module.css +35 -0
- package/app/components/sidebar/case-import/components/CasePreviewSection.tsx +59 -3
- package/app/components/sidebar/case-import/components/ConfirmationDialog.tsx +2 -4
- package/app/components/sidebar/case-import/components/ConfirmationPreviewSection.tsx +1 -1
- package/app/components/sidebar/notes/class-details-shared.ts +2 -2
- package/app/components/toast/toast.module.css +36 -0
- package/app/components/toast/toast.tsx +6 -2
- package/app/components/user/manage-profile.tsx +4 -3
- package/app/config-example/config.json +1 -2
- package/app/root.tsx +0 -7
- package/app/routes/_index.tsx +1 -1
- package/app/routes/auth/login.example.tsx +22 -103
- package/app/routes/auth/route.ts +1 -1
- package/app/routes/striae/striae.tsx +53 -59
- package/app/services/firebase/index.ts +0 -3
- package/app/types/export.ts +1 -2
- package/app/utils/auth/index.ts +0 -1
- package/app/utils/data/permissions.ts +3 -2
- package/package.json +9 -16
- package/public/_headers +0 -4
- package/public/_routes.json +0 -1
- package/worker-configuration.d.ts +20 -17
- package/workers/audit-worker/src/audit-worker.example.ts +9 -806
- package/workers/audit-worker/src/config.ts +7 -0
- package/workers/audit-worker/src/crypto/data-at-rest.ts +410 -0
- package/workers/audit-worker/src/handlers/audit-routes.ts +125 -0
- package/workers/audit-worker/src/storage/audit-storage.ts +99 -0
- package/workers/audit-worker/src/types.ts +56 -0
- package/workers/audit-worker/worker-configuration.d.ts +1 -1
- package/workers/audit-worker/wrangler.jsonc.example +1 -1
- package/workers/data-worker/src/config.ts +11 -0
- package/workers/data-worker/src/data-worker.example.ts +21 -942
- package/workers/data-worker/src/handlers/decrypt-export.ts +118 -0
- package/workers/data-worker/src/handlers/signing.ts +174 -0
- package/workers/data-worker/src/handlers/storage-routes.ts +129 -0
- package/workers/data-worker/src/registry/key-registry.ts +368 -0
- package/workers/data-worker/src/types.ts +46 -0
- package/workers/data-worker/worker-configuration.d.ts +1 -1
- package/workers/data-worker/wrangler.jsonc.example +1 -1
- package/workers/image-worker/worker-configuration.d.ts +1 -1
- package/workers/image-worker/wrangler.jsonc.example +1 -1
- package/workers/pdf-worker/worker-configuration.d.ts +2 -3
- package/workers/pdf-worker/wrangler.jsonc.example +1 -1
- package/workers/user-worker/src/auth.ts +30 -0
- package/workers/user-worker/src/cleanup/account-deletion.ts +337 -0
- package/workers/user-worker/src/config.ts +4 -0
- package/workers/user-worker/src/encryption-utils.ts +25 -0
- package/workers/user-worker/src/firebase/admin.ts +152 -0
- package/workers/user-worker/src/handlers/user-routes.ts +242 -0
- package/workers/user-worker/src/registry/user-kv.ts +172 -0
- package/workers/user-worker/src/storage/user-records.ts +34 -0
- package/workers/user-worker/src/types.ts +106 -0
- package/workers/user-worker/src/user-worker.example.ts +18 -964
- package/workers/user-worker/worker-configuration.d.ts +4 -2
- package/workers/user-worker/wrangler.jsonc.example +12 -1
- package/wrangler.toml.example +1 -1
- package/app/components/actions/case-export/data-processing.ts +0 -223
- package/app/components/sidebar/case-export/case-export.module.css +0 -418
- package/app/components/sidebar/case-export/case-export.tsx +0 -310
- package/app/types/exceljs-bare.d.ts +0 -9
- package/app/utils/auth/auth.ts +0 -11
- package/public/.well-known/security.txt +0 -6
- package/public/favicon.ico +0 -0
- package/public/icon-256.png +0 -0
- package/public/icon-512.png +0 -0
- package/public/manifest.json +0 -39
- package/public/shortcut.png +0 -0
- package/public/social-image.png +0 -0
- package/public/vendor/exceljs.LICENSE +0 -22
- package/public/vendor/exceljs.bare.min.js +0 -45
- package/scripts/deploy-all.sh +0 -166
- package/scripts/deploy-config/modules/env-utils.sh +0 -322
- package/scripts/deploy-config/modules/keys.sh +0 -404
- package/scripts/deploy-config/modules/prompt.sh +0 -372
- package/scripts/deploy-config/modules/scaffolding.sh +0 -344
- package/scripts/deploy-config/modules/validation.sh +0 -365
- package/scripts/deploy-config.sh +0 -236
- package/scripts/deploy-pages-secrets.sh +0 -231
- package/scripts/deploy-pages.sh +0 -34
- package/scripts/deploy-primershear-emails.sh +0 -167
- package/scripts/deploy-worker-secrets.sh +0 -374
- package/scripts/dev.cjs +0 -23
- package/scripts/install-workers.sh +0 -88
- package/scripts/run-eslint.cjs +0 -43
- package/scripts/update-compatibility-dates.cjs +0 -124
- package/scripts/update-markdown-versions.cjs +0 -43
- package/workers/keys-worker/package.json +0 -18
- package/workers/keys-worker/src/keys.example.ts +0 -67
- package/workers/keys-worker/src/keys.ts +0 -67
- package/workers/keys-worker/worker-configuration.d.ts +0 -7447
- package/workers/keys-worker/wrangler.jsonc.example +0 -15
|
@@ -1,310 +0,0 @@
|
|
|
1
|
-
import { useState, useEffect, useContext } from 'react';
|
|
2
|
-
import styles from './case-export.module.css';
|
|
3
|
-
import { AuthContext } from '~/contexts/auth.context';
|
|
4
|
-
import { useOverlayDismiss } from '~/hooks/useOverlayDismiss';
|
|
5
|
-
import { getCaseConfirmations, exportConfirmationData } from '../../actions/confirm-export';
|
|
6
|
-
|
|
7
|
-
export type ExportFormat = 'json' | 'csv';
|
|
8
|
-
|
|
9
|
-
interface CaseExportProps {
|
|
10
|
-
isOpen: boolean;
|
|
11
|
-
onClose: () => void;
|
|
12
|
-
onExport: (caseNumber: string, format: ExportFormat, includeImages?: boolean, onProgress?: (progress: number, label: string) => void) => Promise<void>;
|
|
13
|
-
onExportAll: (onProgress: (current: number, total: number, caseName: string) => void, format: ExportFormat) => Promise<void>;
|
|
14
|
-
currentCaseNumber?: string;
|
|
15
|
-
isReadOnly?: boolean;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export const CaseExport = ({
|
|
19
|
-
isOpen,
|
|
20
|
-
onClose,
|
|
21
|
-
onExport,
|
|
22
|
-
onExportAll,
|
|
23
|
-
currentCaseNumber = '',
|
|
24
|
-
isReadOnly = false
|
|
25
|
-
}: CaseExportProps) => {
|
|
26
|
-
const { user } = useContext(AuthContext);
|
|
27
|
-
const [caseNumber, setCaseNumber] = useState(currentCaseNumber);
|
|
28
|
-
const [isExporting, setIsExporting] = useState(false);
|
|
29
|
-
const [isExportingAll, setIsExportingAll] = useState(false);
|
|
30
|
-
const [isExportingConfirmations, setIsExportingConfirmations] = useState(false);
|
|
31
|
-
const [error, setError] = useState<string>('');
|
|
32
|
-
const [exportProgress, setExportProgress] = useState<{ current: number; total: number; caseName: string; mode?: 'single' | 'all' } | null>(null);
|
|
33
|
-
const [selectedFormat, setSelectedFormat] = useState<ExportFormat>('json');
|
|
34
|
-
const [includeImages, setIncludeImages] = useState(false);
|
|
35
|
-
const [hasConfirmationData, setHasConfirmationData] = useState(false);
|
|
36
|
-
const {
|
|
37
|
-
requestClose,
|
|
38
|
-
overlayProps,
|
|
39
|
-
getCloseButtonProps
|
|
40
|
-
} = useOverlayDismiss({
|
|
41
|
-
isOpen,
|
|
42
|
-
onClose,
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
// Update caseNumber when currentCaseNumber prop changes
|
|
46
|
-
useEffect(() => {
|
|
47
|
-
setCaseNumber(currentCaseNumber);
|
|
48
|
-
}, [currentCaseNumber]);
|
|
49
|
-
|
|
50
|
-
// Disable images option when exporting all cases or when no case number is entered
|
|
51
|
-
useEffect(() => {
|
|
52
|
-
if ((isExportingAll || !caseNumber.trim()) && includeImages) {
|
|
53
|
-
setIncludeImages(false);
|
|
54
|
-
}
|
|
55
|
-
}, [isExportingAll, caseNumber, includeImages]);
|
|
56
|
-
|
|
57
|
-
// Check for confirmation data when case changes (for read-only cases)
|
|
58
|
-
useEffect(() => {
|
|
59
|
-
const checkConfirmationData = async () => {
|
|
60
|
-
if (isReadOnly && user && caseNumber.trim()) {
|
|
61
|
-
try {
|
|
62
|
-
const confirmations = await getCaseConfirmations(user, caseNumber.trim());
|
|
63
|
-
const hasData = !!confirmations && Object.keys(confirmations).length > 0;
|
|
64
|
-
setHasConfirmationData(hasData);
|
|
65
|
-
} catch (error) {
|
|
66
|
-
console.error('Failed to check confirmation data:', error);
|
|
67
|
-
setHasConfirmationData(false);
|
|
68
|
-
}
|
|
69
|
-
} else {
|
|
70
|
-
setHasConfirmationData(false);
|
|
71
|
-
}
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
checkConfirmationData();
|
|
75
|
-
}, [isReadOnly, user, caseNumber]);
|
|
76
|
-
|
|
77
|
-
// Additional useEffect to check when modal opens
|
|
78
|
-
useEffect(() => {
|
|
79
|
-
if (isOpen && isReadOnly && user && caseNumber.trim()) {
|
|
80
|
-
const checkOnOpen = async () => {
|
|
81
|
-
try {
|
|
82
|
-
const confirmations = await getCaseConfirmations(user, caseNumber.trim());
|
|
83
|
-
const hasData = !!confirmations && Object.keys(confirmations).length > 0;
|
|
84
|
-
setHasConfirmationData(hasData);
|
|
85
|
-
} catch (error) {
|
|
86
|
-
console.error('Modal open confirmation check failed:', error);
|
|
87
|
-
setHasConfirmationData(false);
|
|
88
|
-
}
|
|
89
|
-
};
|
|
90
|
-
checkOnOpen();
|
|
91
|
-
}
|
|
92
|
-
}, [isOpen, isReadOnly, user, caseNumber]);
|
|
93
|
-
|
|
94
|
-
// Force JSON format and disable images for read-only cases
|
|
95
|
-
useEffect(() => {
|
|
96
|
-
if (isReadOnly) {
|
|
97
|
-
setSelectedFormat('json');
|
|
98
|
-
setIncludeImages(false);
|
|
99
|
-
}
|
|
100
|
-
}, [isReadOnly]);
|
|
101
|
-
|
|
102
|
-
if (!isOpen) return null;
|
|
103
|
-
|
|
104
|
-
const handleExport = async () => {
|
|
105
|
-
if (!caseNumber.trim()) {
|
|
106
|
-
setError('Please enter a case number');
|
|
107
|
-
return;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
setIsExporting(true);
|
|
111
|
-
setError('');
|
|
112
|
-
setExportProgress(null);
|
|
113
|
-
|
|
114
|
-
try {
|
|
115
|
-
await onExport(caseNumber.trim(), selectedFormat, includeImages, (progress, label) => {
|
|
116
|
-
setExportProgress({ current: progress, total: 100, caseName: label, mode: 'single' });
|
|
117
|
-
});
|
|
118
|
-
requestClose();
|
|
119
|
-
} catch (error) {
|
|
120
|
-
console.error('Export failed:', error);
|
|
121
|
-
setError(error instanceof Error ? error.message : 'Export failed. Please try again.');
|
|
122
|
-
} finally {
|
|
123
|
-
setIsExporting(false);
|
|
124
|
-
setExportProgress(null);
|
|
125
|
-
}
|
|
126
|
-
};
|
|
127
|
-
|
|
128
|
-
const handleExportAll = async () => {
|
|
129
|
-
setIsExportingAll(true);
|
|
130
|
-
setError('');
|
|
131
|
-
setExportProgress(null); // Don't show progress until we have real data
|
|
132
|
-
|
|
133
|
-
try {
|
|
134
|
-
await onExportAll((current: number, total: number, caseName: string) => {
|
|
135
|
-
setExportProgress({ current, total, caseName });
|
|
136
|
-
}, selectedFormat);
|
|
137
|
-
requestClose();
|
|
138
|
-
} catch (error) {
|
|
139
|
-
console.error('Export all failed:', error);
|
|
140
|
-
setError(error instanceof Error ? error.message : 'Export all cases failed. Please try again.');
|
|
141
|
-
} finally {
|
|
142
|
-
setIsExportingAll(false);
|
|
143
|
-
setExportProgress(null);
|
|
144
|
-
}
|
|
145
|
-
};
|
|
146
|
-
|
|
147
|
-
const handleExportConfirmations = async () => {
|
|
148
|
-
if (!caseNumber.trim() || !user) {
|
|
149
|
-
setError('Unable to export confirmation data');
|
|
150
|
-
return;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
setIsExportingConfirmations(true);
|
|
154
|
-
setError('');
|
|
155
|
-
|
|
156
|
-
try {
|
|
157
|
-
await exportConfirmationData(user, caseNumber.trim());
|
|
158
|
-
requestClose();
|
|
159
|
-
} catch (error) {
|
|
160
|
-
console.error('Confirmation export failed:', error);
|
|
161
|
-
setError(error instanceof Error ? error.message : 'Confirmation export failed. Please try again.');
|
|
162
|
-
} finally {
|
|
163
|
-
setIsExportingConfirmations(false);
|
|
164
|
-
}
|
|
165
|
-
};
|
|
166
|
-
|
|
167
|
-
return (
|
|
168
|
-
<div
|
|
169
|
-
className={styles.overlay}
|
|
170
|
-
aria-label="Close case export dialog"
|
|
171
|
-
{...overlayProps}
|
|
172
|
-
>
|
|
173
|
-
<div className={styles.modal}>
|
|
174
|
-
<div className={styles.header}>
|
|
175
|
-
<h2 className={styles.title}>Export Case Data</h2>
|
|
176
|
-
<button className={styles.closeButton} {...getCloseButtonProps({ ariaLabel: 'Close case export dialog' })}>
|
|
177
|
-
×
|
|
178
|
-
</button>
|
|
179
|
-
</div>
|
|
180
|
-
|
|
181
|
-
<div className={styles.content}>
|
|
182
|
-
<div className={styles.fieldGroup}>
|
|
183
|
-
{/* 1. Case number input */}
|
|
184
|
-
<div className={styles.inputGroup}>
|
|
185
|
-
<input
|
|
186
|
-
id="caseNumber"
|
|
187
|
-
type="text"
|
|
188
|
-
className={styles.input}
|
|
189
|
-
value={caseNumber}
|
|
190
|
-
onChange={(e) => {
|
|
191
|
-
setCaseNumber(e.target.value);
|
|
192
|
-
if (error) setError('');
|
|
193
|
-
}}
|
|
194
|
-
placeholder="Enter case number"
|
|
195
|
-
disabled={isExporting || isExportingAll || isReadOnly}
|
|
196
|
-
/>
|
|
197
|
-
</div>
|
|
198
|
-
|
|
199
|
-
{/* 2. Format choice - disabled for read-only cases */}
|
|
200
|
-
<div className={styles.formatSelector}>
|
|
201
|
-
<span className={styles.formatLabel}>Data Format:</span>
|
|
202
|
-
<div className={styles.formatToggle}>
|
|
203
|
-
<button
|
|
204
|
-
type="button"
|
|
205
|
-
className={`${styles.formatOption} ${selectedFormat === 'json' ? styles.formatOptionActive : ''}`}
|
|
206
|
-
onClick={() => setSelectedFormat('json')}
|
|
207
|
-
disabled={isExporting || isExportingAll || isReadOnly}
|
|
208
|
-
title="JSON for case imports"
|
|
209
|
-
>
|
|
210
|
-
JSON
|
|
211
|
-
</button>
|
|
212
|
-
<button
|
|
213
|
-
type="button"
|
|
214
|
-
className={`${styles.formatOption} ${selectedFormat === 'csv' ? styles.formatOptionActive : ''}`}
|
|
215
|
-
onClick={() => setSelectedFormat('csv')}
|
|
216
|
-
disabled={isExporting || isExportingAll || isReadOnly}
|
|
217
|
-
title="CSV for single case, Excel (.xlsx) with multiple worksheets for all cases"
|
|
218
|
-
>
|
|
219
|
-
CSV/Excel
|
|
220
|
-
</button>
|
|
221
|
-
</div>
|
|
222
|
-
</div>
|
|
223
|
-
|
|
224
|
-
{/* 3. Image inclusion option - disabled for read-only cases */}
|
|
225
|
-
<div className={styles.imageOption}>
|
|
226
|
-
<div className={styles.checkboxLabel}>
|
|
227
|
-
<input
|
|
228
|
-
id="includeImagesOption"
|
|
229
|
-
type="checkbox"
|
|
230
|
-
className={styles.checkbox}
|
|
231
|
-
checked={includeImages}
|
|
232
|
-
onChange={(e) => setIncludeImages(e.target.checked)}
|
|
233
|
-
disabled={!caseNumber.trim() || isExporting || isExportingAll || isReadOnly}
|
|
234
|
-
aria-label="Include images in ZIP export"
|
|
235
|
-
/>
|
|
236
|
-
<label htmlFor="includeImagesOption" className={styles.checkboxText}>
|
|
237
|
-
<span>Include Images (ZIP)</span>
|
|
238
|
-
<span className={styles.checkboxTooltip}>
|
|
239
|
-
Available for single case exports only. Downloads a ZIP file containing data and all associated image files. Case imports support only JSON data format.
|
|
240
|
-
</span>
|
|
241
|
-
</label>
|
|
242
|
-
</div>
|
|
243
|
-
</div>
|
|
244
|
-
|
|
245
|
-
{/* 4. Export buttons (case OR all cases) */}
|
|
246
|
-
<div className={styles.inputGroup}>
|
|
247
|
-
<button
|
|
248
|
-
className={isReadOnly ? styles.confirmationExportButton : styles.exportButton}
|
|
249
|
-
onClick={isReadOnly ? handleExportConfirmations : handleExport}
|
|
250
|
-
disabled={!caseNumber.trim() || isExporting || isExportingAll || isExportingConfirmations || (isReadOnly && !hasConfirmationData)}
|
|
251
|
-
>
|
|
252
|
-
{isExporting || isExportingConfirmations ? 'Exporting...' :
|
|
253
|
-
isReadOnly ? 'Export Confirmation Data' : 'Export Case Data'}
|
|
254
|
-
</button>
|
|
255
|
-
</div>
|
|
256
|
-
|
|
257
|
-
{/* Hide "Export All Cases" for read-only cases */}
|
|
258
|
-
{!isReadOnly && (
|
|
259
|
-
<>
|
|
260
|
-
<div className={styles.divider}>
|
|
261
|
-
<span>OR</span>
|
|
262
|
-
</div>
|
|
263
|
-
|
|
264
|
-
<div className={styles.exportAllSection}>
|
|
265
|
-
<button
|
|
266
|
-
className={styles.exportAllButton}
|
|
267
|
-
onClick={handleExportAll}
|
|
268
|
-
disabled={isExporting || isExportingAll}
|
|
269
|
-
>
|
|
270
|
-
{isExportingAll ? 'Exporting All Cases...' : 'Export All Cases'}
|
|
271
|
-
</button>
|
|
272
|
-
</div>
|
|
273
|
-
</>
|
|
274
|
-
)}
|
|
275
|
-
|
|
276
|
-
{exportProgress && exportProgress.total > 0 && (
|
|
277
|
-
<div className={styles.progressSection}>
|
|
278
|
-
<div className={styles.progressText}>
|
|
279
|
-
{exportProgress.mode === 'single'
|
|
280
|
-
? `${exportProgress.caseName} (${exportProgress.current}%)`
|
|
281
|
-
: `Exporting case ${exportProgress.current} of ${exportProgress.total}: ${exportProgress.caseName}`}
|
|
282
|
-
</div>
|
|
283
|
-
<div className={styles.progressBar}>
|
|
284
|
-
<div
|
|
285
|
-
className={styles.progressFill}
|
|
286
|
-
style={{ width: `${(exportProgress.current / exportProgress.total) * 100}%` }}
|
|
287
|
-
/>
|
|
288
|
-
</div>
|
|
289
|
-
</div>
|
|
290
|
-
)}
|
|
291
|
-
|
|
292
|
-
{(isExporting || isExportingAll) && !exportProgress && (
|
|
293
|
-
<div className={styles.progressSection}>
|
|
294
|
-
<div className={styles.progressText}>
|
|
295
|
-
Preparing export...
|
|
296
|
-
</div>
|
|
297
|
-
</div>
|
|
298
|
-
)}
|
|
299
|
-
|
|
300
|
-
{error && (
|
|
301
|
-
<div className={styles.error}>
|
|
302
|
-
{error}
|
|
303
|
-
</div>
|
|
304
|
-
)}
|
|
305
|
-
</div>
|
|
306
|
-
</div>
|
|
307
|
-
</div>
|
|
308
|
-
</div>
|
|
309
|
-
);
|
|
310
|
-
};
|
package/app/utils/auth/auth.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import paths from '~/config/config.json';
|
|
2
|
-
|
|
3
|
-
const ACCOUNT_HASH = typeof paths.account_hash === 'string' ? paths.account_hash.trim() : '';
|
|
4
|
-
|
|
5
|
-
export async function getAccountHash(): Promise<string> {
|
|
6
|
-
if (!ACCOUNT_HASH) {
|
|
7
|
-
throw new Error('ACCOUNT_HASH is not configured in app/config/config.json');
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
return ACCOUNT_HASH;
|
|
11
|
-
}
|
package/public/favicon.ico
DELETED
|
Binary file
|
package/public/icon-256.png
DELETED
|
Binary file
|
package/public/icon-512.png
DELETED
|
Binary file
|
package/public/manifest.json
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"id": "/",
|
|
3
|
-
"name": "Striae: A Firearms Examiner's Comparison Companion",
|
|
4
|
-
"short_name": "Striae",
|
|
5
|
-
"description": "Striae is a specialized, cloud-native platform designed to streamline forensic firearms identification by providing an intuitive environment for digital comparison image annotation, authenticated confirmations, and automated report generation.",
|
|
6
|
-
"start_url": "/",
|
|
7
|
-
"scope": "/",
|
|
8
|
-
"display": "standalone",
|
|
9
|
-
"orientation": "any",
|
|
10
|
-
"lang": "en-US",
|
|
11
|
-
"dir": "ltr",
|
|
12
|
-
"theme_color": "#377087",
|
|
13
|
-
"background_color": "#f5f5f5",
|
|
14
|
-
"categories": [
|
|
15
|
-
"business",
|
|
16
|
-
"productivity",
|
|
17
|
-
"utilities"
|
|
18
|
-
],
|
|
19
|
-
"icons": [
|
|
20
|
-
{
|
|
21
|
-
"src": "shortcut.png",
|
|
22
|
-
"sizes": "64x64",
|
|
23
|
-
"type": "image/png",
|
|
24
|
-
"purpose": "any"
|
|
25
|
-
},
|
|
26
|
-
{
|
|
27
|
-
"src": "icon-256.png",
|
|
28
|
-
"sizes": "256x256",
|
|
29
|
-
"type": "image/png",
|
|
30
|
-
"purpose": "any"
|
|
31
|
-
},
|
|
32
|
-
{
|
|
33
|
-
"src": "icon-512.png",
|
|
34
|
-
"sizes": "512x512",
|
|
35
|
-
"type": "image/png",
|
|
36
|
-
"purpose": "any"
|
|
37
|
-
}
|
|
38
|
-
]
|
|
39
|
-
}
|
package/public/shortcut.png
DELETED
|
Binary file
|
package/public/social-image.png
DELETED
|
Binary file
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
The MIT License (MIT)
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2014-2019 Guyon Roche
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
22
|
-
|