@oneuptime/common 9.3.20 → 9.4.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/Models/DatabaseModels/IncomingCallLog.ts +521 -0
- package/Models/DatabaseModels/IncomingCallLogItem.ts +463 -0
- package/Models/DatabaseModels/IncomingCallPolicy.ts +811 -0
- package/Models/DatabaseModels/IncomingCallPolicyEscalationRule.ts +597 -0
- package/Models/DatabaseModels/Index.ts +18 -0
- package/Models/DatabaseModels/ProjectSCIMLog.ts +422 -0
- package/Models/DatabaseModels/StatusPageSCIMLog.ts +455 -0
- package/Models/DatabaseModels/User.ts +0 -15
- package/Models/DatabaseModels/UserIncomingCallNumber.ts +296 -0
- package/Server/API/UserIncomingCallNumberAPI.ts +128 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1768583966447-MigrationName.ts +121 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1768647802022-RemoveAlertPhoneNumberFromUser.ts +22 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1768649699509-MigrationName.ts +787 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1768682071562-MigrationName.ts +29 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +8 -0
- package/Server/Services/IncomingCallLogItemService.ts +10 -0
- package/Server/Services/IncomingCallLogService.ts +10 -0
- package/Server/Services/IncomingCallPolicyEscalationRuleService.ts +267 -0
- package/Server/Services/IncomingCallPolicyService.ts +10 -0
- package/Server/Services/Index.ts +7 -0
- package/Server/Services/ProjectSCIMLogService.ts +11 -0
- package/Server/Services/StatusPageSCIMLogService.ts +11 -0
- package/Server/Services/UserCallService.ts +31 -0
- package/Server/Services/UserIncomingCallNumberService.ts +258 -0
- package/Server/Services/UserSmsService.ts +31 -0
- package/Server/Utils/AnalyticsDatabase/Statement.ts +2 -2
- package/Server/Utils/StartServer.ts +5 -0
- package/Tests/UI/Components/Input.test.tsx +33 -0
- package/Types/Call/CallProvider.ts +99 -0
- package/Types/Call/CallProviderType.ts +6 -0
- package/Types/Date.ts +18 -0
- package/Types/Icon/IconProp.ts +1 -0
- package/Types/IncomingCall/IncomingCallStatus.ts +13 -0
- package/Types/Permission.ts +126 -0
- package/Types/Phone.ts +53 -4
- package/Types/SCIM/SCIMLogStatus.ts +7 -0
- package/UI/Components/Date/StartAndEndDate.tsx +35 -11
- package/UI/Components/Diagram/ConceptCards.tsx +74 -0
- package/UI/Components/Diagram/HorizontalStepChain.tsx +92 -0
- package/UI/Components/Diagram/Index.ts +11 -0
- package/UI/Components/Diagram/NumberedSteps.tsx +77 -0
- package/UI/Components/Diagram/VerticalFlowSteps.tsx +59 -0
- package/UI/Components/Filters/FilterViewer.tsx +7 -0
- package/UI/Components/Icon/Icon.tsx +10 -0
- package/UI/Components/Input/Input.tsx +7 -0
- package/UI/Components/SimpleLogViewer/SimpleLogViewer.tsx +86 -2
- package/build/dist/Models/DatabaseModels/IncomingCallLog.js +565 -0
- package/build/dist/Models/DatabaseModels/IncomingCallLog.js.map +1 -0
- package/build/dist/Models/DatabaseModels/IncomingCallLogItem.js +497 -0
- package/build/dist/Models/DatabaseModels/IncomingCallLogItem.js.map +1 -0
- package/build/dist/Models/DatabaseModels/IncomingCallPolicy.js +840 -0
- package/build/dist/Models/DatabaseModels/IncomingCallPolicy.js.map +1 -0
- package/build/dist/Models/DatabaseModels/IncomingCallPolicyEscalationRule.js +619 -0
- package/build/dist/Models/DatabaseModels/IncomingCallPolicyEscalationRule.js.map +1 -0
- package/build/dist/Models/DatabaseModels/Index.js +16 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ProjectSCIMLog.js +455 -0
- package/build/dist/Models/DatabaseModels/ProjectSCIMLog.js.map +1 -0
- package/build/dist/Models/DatabaseModels/StatusPageSCIMLog.js +486 -0
- package/build/dist/Models/DatabaseModels/StatusPageSCIMLog.js.map +1 -0
- package/build/dist/Models/DatabaseModels/User.js +0 -16
- package/build/dist/Models/DatabaseModels/User.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserIncomingCallNumber.js +315 -0
- package/build/dist/Models/DatabaseModels/UserIncomingCallNumber.js.map +1 -0
- package/build/dist/Server/API/UserIncomingCallNumberAPI.js +72 -0
- package/build/dist/Server/API/UserIncomingCallNumberAPI.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1768583966447-MigrationName.js +48 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1768583966447-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1768647802022-RemoveAlertPhoneNumberFromUser.js +34 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1768647802022-RemoveAlertPhoneNumberFromUser.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1768649699509-MigrationName.js +270 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1768649699509-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1768682071562-MigrationName.js +16 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1768682071562-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +8 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Services/IncomingCallLogItemService.js +9 -0
- package/build/dist/Server/Services/IncomingCallLogItemService.js.map +1 -0
- package/build/dist/Server/Services/IncomingCallLogService.js +9 -0
- package/build/dist/Server/Services/IncomingCallLogService.js.map +1 -0
- package/build/dist/Server/Services/IncomingCallPolicyEscalationRuleService.js +197 -0
- package/build/dist/Server/Services/IncomingCallPolicyEscalationRuleService.js.map +1 -0
- package/build/dist/Server/Services/IncomingCallPolicyService.js +9 -0
- package/build/dist/Server/Services/IncomingCallPolicyService.js.map +1 -0
- package/build/dist/Server/Services/Index.js +6 -0
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/ProjectSCIMLogService.js +10 -0
- package/build/dist/Server/Services/ProjectSCIMLogService.js.map +1 -0
- package/build/dist/Server/Services/StatusPageSCIMLogService.js +10 -0
- package/build/dist/Server/Services/StatusPageSCIMLogService.js.map +1 -0
- package/build/dist/Server/Services/UserCallService.js +21 -0
- package/build/dist/Server/Services/UserCallService.js.map +1 -1
- package/build/dist/Server/Services/UserIncomingCallNumberService.js +225 -0
- package/build/dist/Server/Services/UserIncomingCallNumberService.js.map +1 -0
- package/build/dist/Server/Services/UserSmsService.js +21 -0
- package/build/dist/Server/Services/UserSmsService.js.map +1 -1
- package/build/dist/Server/Utils/AnalyticsDatabase/Statement.js +2 -2
- package/build/dist/Server/Utils/AnalyticsDatabase/Statement.js.map +1 -1
- package/build/dist/Server/Utils/StartServer.js +5 -0
- package/build/dist/Server/Utils/StartServer.js.map +1 -1
- package/build/dist/Tests/UI/Components/Input.test.js +10 -0
- package/build/dist/Tests/UI/Components/Input.test.js.map +1 -1
- package/build/dist/Types/Call/CallProvider.js +2 -0
- package/build/dist/Types/Call/CallProvider.js.map +1 -0
- package/build/dist/Types/Call/CallProviderType.js +7 -0
- package/build/dist/Types/Call/CallProviderType.js.map +1 -0
- package/build/dist/Types/Date.js +17 -3
- package/build/dist/Types/Date.js.map +1 -1
- package/build/dist/Types/Icon/IconProp.js +1 -0
- package/build/dist/Types/Icon/IconProp.js.map +1 -1
- package/build/dist/Types/IncomingCall/IncomingCallStatus.js +14 -0
- package/build/dist/Types/IncomingCall/IncomingCallStatus.js.map +1 -0
- package/build/dist/Types/Permission.js +104 -0
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/Phone.js +47 -3
- package/build/dist/Types/Phone.js.map +1 -1
- package/build/dist/Types/SCIM/SCIMLogStatus.js +8 -0
- package/build/dist/Types/SCIM/SCIMLogStatus.js.map +1 -0
- package/build/dist/UI/Components/Date/StartAndEndDate.js +13 -13
- package/build/dist/UI/Components/Date/StartAndEndDate.js.map +1 -1
- package/build/dist/UI/Components/Diagram/ConceptCards.js +30 -0
- package/build/dist/UI/Components/Diagram/ConceptCards.js.map +1 -0
- package/build/dist/UI/Components/Diagram/HorizontalStepChain.js +30 -0
- package/build/dist/UI/Components/Diagram/HorizontalStepChain.js.map +1 -0
- package/build/dist/UI/Components/Diagram/Index.js +5 -0
- package/build/dist/UI/Components/Diagram/Index.js.map +1 -0
- package/build/dist/UI/Components/Diagram/NumberedSteps.js +18 -0
- package/build/dist/UI/Components/Diagram/NumberedSteps.js.map +1 -0
- package/build/dist/UI/Components/Diagram/VerticalFlowSteps.js +16 -0
- package/build/dist/UI/Components/Diagram/VerticalFlowSteps.js.map +1 -0
- package/build/dist/UI/Components/Filters/FilterViewer.js +6 -5
- package/build/dist/UI/Components/Filters/FilterViewer.js.map +1 -1
- package/build/dist/UI/Components/Icon/Icon.js +4 -0
- package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
- package/build/dist/UI/Components/Input/Input.js +4 -1
- package/build/dist/UI/Components/Input/Input.js.map +1 -1
- package/build/dist/UI/Components/SimpleLogViewer/SimpleLogViewer.js +30 -1
- package/build/dist/UI/Components/SimpleLogViewer/SimpleLogViewer.js.map +1 -1
- package/package.json +1 -1
package/Types/Phone.ts
CHANGED
|
@@ -13,7 +13,7 @@ export default class Phone extends DatabaseProperty {
|
|
|
13
13
|
public static pickPhoneNumberToSendSMSOrCallFrom(data: {
|
|
14
14
|
to: Phone | string;
|
|
15
15
|
primaryPhoneNumberToPickFrom: Phone | string;
|
|
16
|
-
|
|
16
|
+
secondaryPhoneNumbersToPickFrom: Phone[] | string[];
|
|
17
17
|
}): Phone {
|
|
18
18
|
/*
|
|
19
19
|
* convert all to string, so that we can compare them
|
|
@@ -28,8 +28,8 @@ export default class Phone extends DatabaseProperty {
|
|
|
28
28
|
? data.primaryPhoneNumberToPickFrom
|
|
29
29
|
: data.primaryPhoneNumberToPickFrom.toString();
|
|
30
30
|
|
|
31
|
-
const
|
|
32
|
-
data.
|
|
31
|
+
const secondaryPhoneNumbersToPickFrom: string[] =
|
|
32
|
+
data.secondaryPhoneNumbersToPickFrom.map((phone: Phone | string) => {
|
|
33
33
|
return typeof phone === "string" ? phone : phone.toString();
|
|
34
34
|
});
|
|
35
35
|
|
|
@@ -51,7 +51,7 @@ export default class Phone extends DatabaseProperty {
|
|
|
51
51
|
return new Phone(primaryPhoneNumberToPickFrom);
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
for (const secondaryPhoneNumber of
|
|
54
|
+
for (const secondaryPhoneNumber of secondaryPhoneNumbersToPickFrom) {
|
|
55
55
|
const secondaryPhoneNumberCountryCode: string = normalizePhoneNumber(
|
|
56
56
|
secondaryPhoneNumber,
|
|
57
57
|
).substring(0, 2);
|
|
@@ -148,4 +148,53 @@ export default class Phone extends DatabaseProperty {
|
|
|
148
148
|
example: { _type: ObjectType.Phone, value: "+1-555-123-4567" },
|
|
149
149
|
});
|
|
150
150
|
}
|
|
151
|
+
|
|
152
|
+
// Map of calling code prefixes to ISO country codes
|
|
153
|
+
private static readonly CALLING_CODE_TO_COUNTRY_MAP: Record<string, string> =
|
|
154
|
+
{
|
|
155
|
+
"+1": "US", // US and Canada
|
|
156
|
+
"+44": "GB", // United Kingdom
|
|
157
|
+
"+61": "AU", // Australia
|
|
158
|
+
"+49": "DE", // Germany
|
|
159
|
+
"+33": "FR", // France
|
|
160
|
+
"+91": "IN", // India
|
|
161
|
+
"+81": "JP", // Japan
|
|
162
|
+
"+86": "CN", // China
|
|
163
|
+
"+55": "BR", // Brazil
|
|
164
|
+
"+52": "MX", // Mexico
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Extract ISO country code from a phone number
|
|
169
|
+
* @param phoneNumber - The phone number (e.g., "+15551234567")
|
|
170
|
+
* @returns ISO country code (e.g., "US") or "US" as default
|
|
171
|
+
*/
|
|
172
|
+
public static getCountryCodeFromPhoneNumber(phoneNumber: string): string {
|
|
173
|
+
for (const [prefix, countryCode] of Object.entries(
|
|
174
|
+
Phone.CALLING_CODE_TO_COUNTRY_MAP,
|
|
175
|
+
)) {
|
|
176
|
+
if (phoneNumber.startsWith(prefix)) {
|
|
177
|
+
return countryCode;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
return "US"; // Default to US if unknown
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Extract area code from a phone number
|
|
185
|
+
* Currently only supports US/Canada (+1) numbers
|
|
186
|
+
* @param phoneNumber - The phone number (e.g., "+15551234567")
|
|
187
|
+
* @returns Area code (e.g., "555") or empty string for non-US/CA numbers
|
|
188
|
+
*/
|
|
189
|
+
public static getAreaCodeFromPhoneNumber(phoneNumber: string): string {
|
|
190
|
+
// For US/Canada numbers (+1), extract the next 3 digits
|
|
191
|
+
if (phoneNumber.startsWith("+1")) {
|
|
192
|
+
const number: string = phoneNumber.substring(2);
|
|
193
|
+
if (number.length >= 3) {
|
|
194
|
+
return number.substring(0, 3);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
// For other countries, area code extraction is more complex
|
|
198
|
+
return "";
|
|
199
|
+
}
|
|
151
200
|
}
|
|
@@ -158,6 +158,9 @@ const StartAndEndDate: DateFilterFunction = (
|
|
|
158
158
|
value={startDateTime || ""}
|
|
159
159
|
placeholder={`Start Date`}
|
|
160
160
|
type={inputType}
|
|
161
|
+
showSecondsForDateTime={
|
|
162
|
+
props.type === StartAndEndDateType.DateTime
|
|
163
|
+
}
|
|
161
164
|
/>
|
|
162
165
|
</div>
|
|
163
166
|
</div>
|
|
@@ -192,6 +195,9 @@ const StartAndEndDate: DateFilterFunction = (
|
|
|
192
195
|
value={endDateTime || ""}
|
|
193
196
|
placeholder={`End Date`}
|
|
194
197
|
type={inputType}
|
|
198
|
+
showSecondsForDateTime={
|
|
199
|
+
props.type === StartAndEndDateType.DateTime
|
|
200
|
+
}
|
|
195
201
|
/>
|
|
196
202
|
</div>
|
|
197
203
|
</div>
|
|
@@ -207,7 +213,10 @@ const StartAndEndDate: DateFilterFunction = (
|
|
|
207
213
|
buttonSize={ButtonSize.Small}
|
|
208
214
|
onClick={() => {
|
|
209
215
|
// set it to past 1 hour
|
|
210
|
-
const endDate: Date =
|
|
216
|
+
const endDate: Date =
|
|
217
|
+
OneUptimeDate.resetSecondsAndMilliseconds(
|
|
218
|
+
OneUptimeDate.getCurrentDate(),
|
|
219
|
+
);
|
|
211
220
|
const startDate: Date = OneUptimeDate.addRemoveHours(
|
|
212
221
|
endDate,
|
|
213
222
|
-1,
|
|
@@ -229,7 +238,10 @@ const StartAndEndDate: DateFilterFunction = (
|
|
|
229
238
|
buttonSize={ButtonSize.Small}
|
|
230
239
|
onClick={() => {
|
|
231
240
|
// set it to past 3 hour
|
|
232
|
-
const endDate: Date =
|
|
241
|
+
const endDate: Date =
|
|
242
|
+
OneUptimeDate.resetSecondsAndMilliseconds(
|
|
243
|
+
OneUptimeDate.getCurrentDate(),
|
|
244
|
+
);
|
|
233
245
|
const startDate: Date = OneUptimeDate.addRemoveHours(
|
|
234
246
|
endDate,
|
|
235
247
|
-3,
|
|
@@ -251,7 +263,9 @@ const StartAndEndDate: DateFilterFunction = (
|
|
|
251
263
|
buttonSize={ButtonSize.Small}
|
|
252
264
|
onClick={() => {
|
|
253
265
|
// set it to past 1 day
|
|
254
|
-
const endDate: Date = OneUptimeDate.
|
|
266
|
+
const endDate: Date = OneUptimeDate.resetSecondsAndMilliseconds(
|
|
267
|
+
OneUptimeDate.getCurrentDate(),
|
|
268
|
+
);
|
|
255
269
|
const startDate: Date = OneUptimeDate.addRemoveDays(
|
|
256
270
|
endDate,
|
|
257
271
|
-1,
|
|
@@ -269,7 +283,9 @@ const StartAndEndDate: DateFilterFunction = (
|
|
|
269
283
|
buttonSize={ButtonSize.Small}
|
|
270
284
|
onClick={() => {
|
|
271
285
|
// set it to past 1 week
|
|
272
|
-
const endDate: Date = OneUptimeDate.
|
|
286
|
+
const endDate: Date = OneUptimeDate.resetSecondsAndMilliseconds(
|
|
287
|
+
OneUptimeDate.getCurrentDate(),
|
|
288
|
+
);
|
|
273
289
|
const startDate: Date = OneUptimeDate.addRemoveDays(
|
|
274
290
|
endDate,
|
|
275
291
|
-7,
|
|
@@ -286,8 +302,10 @@ const StartAndEndDate: DateFilterFunction = (
|
|
|
286
302
|
}
|
|
287
303
|
buttonSize={ButtonSize.Small}
|
|
288
304
|
onClick={() => {
|
|
289
|
-
// set it to past
|
|
290
|
-
const endDate: Date = OneUptimeDate.
|
|
305
|
+
// set it to past 2 weeks
|
|
306
|
+
const endDate: Date = OneUptimeDate.resetSecondsAndMilliseconds(
|
|
307
|
+
OneUptimeDate.getCurrentDate(),
|
|
308
|
+
);
|
|
291
309
|
const startDate: Date = OneUptimeDate.addRemoveDays(
|
|
292
310
|
endDate,
|
|
293
311
|
-14,
|
|
@@ -305,8 +323,10 @@ const StartAndEndDate: DateFilterFunction = (
|
|
|
305
323
|
}
|
|
306
324
|
buttonSize={ButtonSize.Small}
|
|
307
325
|
onClick={() => {
|
|
308
|
-
// set it to past
|
|
309
|
-
const endDate: Date = OneUptimeDate.
|
|
326
|
+
// set it to past 3 weeks
|
|
327
|
+
const endDate: Date = OneUptimeDate.resetSecondsAndMilliseconds(
|
|
328
|
+
OneUptimeDate.getCurrentDate(),
|
|
329
|
+
);
|
|
310
330
|
const startDate: Date = OneUptimeDate.addRemoveDays(
|
|
311
331
|
endDate,
|
|
312
332
|
-21,
|
|
@@ -325,7 +345,9 @@ const StartAndEndDate: DateFilterFunction = (
|
|
|
325
345
|
buttonSize={ButtonSize.Small}
|
|
326
346
|
onClick={() => {
|
|
327
347
|
// set it to past 1 month
|
|
328
|
-
const endDate: Date = OneUptimeDate.
|
|
348
|
+
const endDate: Date = OneUptimeDate.resetSecondsAndMilliseconds(
|
|
349
|
+
OneUptimeDate.getCurrentDate(),
|
|
350
|
+
);
|
|
329
351
|
const startDate: Date = OneUptimeDate.addRemoveMonths(
|
|
330
352
|
endDate,
|
|
331
353
|
-1,
|
|
@@ -343,8 +365,10 @@ const StartAndEndDate: DateFilterFunction = (
|
|
|
343
365
|
}
|
|
344
366
|
buttonSize={ButtonSize.Small}
|
|
345
367
|
onClick={() => {
|
|
346
|
-
// set it to past
|
|
347
|
-
const endDate: Date = OneUptimeDate.
|
|
368
|
+
// set it to past 3 months
|
|
369
|
+
const endDate: Date = OneUptimeDate.resetSecondsAndMilliseconds(
|
|
370
|
+
OneUptimeDate.getCurrentDate(),
|
|
371
|
+
);
|
|
348
372
|
const startDate: Date = OneUptimeDate.addRemoveMonths(
|
|
349
373
|
endDate,
|
|
350
374
|
-3,
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import React, { FunctionComponent, ReactElement } from "react";
|
|
2
|
+
import Icon from "../Icon/Icon";
|
|
3
|
+
import IconProp from "../../../Types/Icon/IconProp";
|
|
4
|
+
import Color from "../../../Types/Color";
|
|
5
|
+
|
|
6
|
+
export interface ConceptCard {
|
|
7
|
+
title: string;
|
|
8
|
+
description: string;
|
|
9
|
+
icon: IconProp;
|
|
10
|
+
iconColor: Color;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface ComponentProps {
|
|
14
|
+
cards: ConceptCard[];
|
|
15
|
+
/** Number of columns in the grid (1-4). Default is 2. */
|
|
16
|
+
columns?: 1 | 2 | 3 | 4 | undefined;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const ConceptCards: FunctionComponent<ComponentProps> = (
|
|
20
|
+
props: ComponentProps,
|
|
21
|
+
): ReactElement => {
|
|
22
|
+
const columns: number = props.columns || 2;
|
|
23
|
+
|
|
24
|
+
const getGridClasses: () => string = (): string => {
|
|
25
|
+
switch (columns) {
|
|
26
|
+
case 1:
|
|
27
|
+
return "grid-cols-1";
|
|
28
|
+
case 2:
|
|
29
|
+
return "grid-cols-1 md:grid-cols-2";
|
|
30
|
+
case 3:
|
|
31
|
+
return "grid-cols-1 md:grid-cols-2 lg:grid-cols-3";
|
|
32
|
+
case 4:
|
|
33
|
+
return "grid-cols-1 md:grid-cols-2 lg:grid-cols-4";
|
|
34
|
+
default:
|
|
35
|
+
return "grid-cols-1 md:grid-cols-2";
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
<div className={`grid ${getGridClasses()} gap-3`}>
|
|
41
|
+
{props.cards.map((card: ConceptCard, index: number) => {
|
|
42
|
+
return (
|
|
43
|
+
<div
|
|
44
|
+
key={index}
|
|
45
|
+
className="border border-gray-200 rounded-md p-3 bg-white hover:border-gray-300 transition-colors"
|
|
46
|
+
>
|
|
47
|
+
<div className="flex items-start space-x-3">
|
|
48
|
+
<div
|
|
49
|
+
className="flex-shrink-0 w-8 h-8 rounded flex items-center justify-center"
|
|
50
|
+
style={{ backgroundColor: `${card.iconColor.toString()}15` }}
|
|
51
|
+
>
|
|
52
|
+
<Icon
|
|
53
|
+
icon={card.icon}
|
|
54
|
+
className="h-4 w-4"
|
|
55
|
+
style={{ color: card.iconColor.toString() }}
|
|
56
|
+
/>
|
|
57
|
+
</div>
|
|
58
|
+
<div className="flex-1 min-w-0">
|
|
59
|
+
<h4 className="text-sm font-medium text-gray-900">
|
|
60
|
+
{card.title}
|
|
61
|
+
</h4>
|
|
62
|
+
<p className="text-sm text-gray-500 mt-1 leading-relaxed">
|
|
63
|
+
{card.description}
|
|
64
|
+
</p>
|
|
65
|
+
</div>
|
|
66
|
+
</div>
|
|
67
|
+
</div>
|
|
68
|
+
);
|
|
69
|
+
})}
|
|
70
|
+
</div>
|
|
71
|
+
);
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
export default ConceptCards;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import React, { FunctionComponent, ReactElement } from "react";
|
|
2
|
+
import Icon from "../Icon/Icon";
|
|
3
|
+
import IconProp from "../../../Types/Icon/IconProp";
|
|
4
|
+
import Color from "../../../Types/Color";
|
|
5
|
+
|
|
6
|
+
export interface ChainStep {
|
|
7
|
+
stepNumber: number;
|
|
8
|
+
title: string;
|
|
9
|
+
description: string;
|
|
10
|
+
color: Color;
|
|
11
|
+
/** Optional label shown below the step number. Default is "Step" */
|
|
12
|
+
stepLabel?: string | undefined;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface ChainEndStep {
|
|
16
|
+
title: string;
|
|
17
|
+
description: string;
|
|
18
|
+
icon: IconProp;
|
|
19
|
+
color: Color;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface ComponentProps {
|
|
23
|
+
steps: ChainStep[];
|
|
24
|
+
endStep?: ChainEndStep | undefined;
|
|
25
|
+
/** Default label for steps. Default is "Step" */
|
|
26
|
+
defaultStepLabel?: string | undefined;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const HorizontalStepChain: FunctionComponent<ComponentProps> = (
|
|
30
|
+
props: ComponentProps,
|
|
31
|
+
): ReactElement => {
|
|
32
|
+
const defaultLabel: string = props.defaultStepLabel || "Step";
|
|
33
|
+
|
|
34
|
+
return (
|
|
35
|
+
<div className="flex items-center flex-wrap gap-3">
|
|
36
|
+
{props.steps.map((step: ChainStep, index: number) => {
|
|
37
|
+
return (
|
|
38
|
+
<React.Fragment key={index}>
|
|
39
|
+
{/* Step */}
|
|
40
|
+
<div className="flex items-center space-x-3">
|
|
41
|
+
<div
|
|
42
|
+
className="w-10 h-10 rounded-full flex items-center justify-center text-white text-sm font-medium"
|
|
43
|
+
style={{ backgroundColor: step.color.toString() }}
|
|
44
|
+
>
|
|
45
|
+
{step.stepNumber}
|
|
46
|
+
</div>
|
|
47
|
+
<div>
|
|
48
|
+
<p className="text-sm font-medium text-gray-900">
|
|
49
|
+
{step.title}
|
|
50
|
+
</p>
|
|
51
|
+
<p className="text-xs text-gray-500">
|
|
52
|
+
{step.stepLabel || defaultLabel} {step.stepNumber} ·{" "}
|
|
53
|
+
{step.description}
|
|
54
|
+
</p>
|
|
55
|
+
</div>
|
|
56
|
+
</div>
|
|
57
|
+
|
|
58
|
+
{/* Arrow */}
|
|
59
|
+
<Icon
|
|
60
|
+
icon={IconProp.ChevronRight}
|
|
61
|
+
className="h-4 w-4 text-gray-300 hidden sm:block"
|
|
62
|
+
/>
|
|
63
|
+
</React.Fragment>
|
|
64
|
+
);
|
|
65
|
+
})}
|
|
66
|
+
|
|
67
|
+
{/* End Step */}
|
|
68
|
+
{props.endStep && (
|
|
69
|
+
<div className="flex items-center space-x-3">
|
|
70
|
+
<div
|
|
71
|
+
className="w-10 h-10 rounded-full flex items-center justify-center"
|
|
72
|
+
style={{ backgroundColor: `${props.endStep.color.toString()}15` }}
|
|
73
|
+
>
|
|
74
|
+
<Icon
|
|
75
|
+
icon={props.endStep.icon}
|
|
76
|
+
className="h-4 w-4"
|
|
77
|
+
style={{ color: props.endStep.color.toString() }}
|
|
78
|
+
/>
|
|
79
|
+
</div>
|
|
80
|
+
<div>
|
|
81
|
+
<p className="text-sm font-medium text-gray-900">
|
|
82
|
+
{props.endStep.title}
|
|
83
|
+
</p>
|
|
84
|
+
<p className="text-xs text-gray-500">{props.endStep.description}</p>
|
|
85
|
+
</div>
|
|
86
|
+
</div>
|
|
87
|
+
)}
|
|
88
|
+
</div>
|
|
89
|
+
);
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
export default HorizontalStepChain;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export { default as VerticalFlowSteps } from "./VerticalFlowSteps";
|
|
2
|
+
export type { FlowStep } from "./VerticalFlowSteps";
|
|
3
|
+
|
|
4
|
+
export { default as HorizontalStepChain } from "./HorizontalStepChain";
|
|
5
|
+
export type { ChainStep, ChainEndStep } from "./HorizontalStepChain";
|
|
6
|
+
|
|
7
|
+
export { default as NumberedSteps } from "./NumberedSteps";
|
|
8
|
+
export type { NumberedStep } from "./NumberedSteps";
|
|
9
|
+
|
|
10
|
+
export { default as ConceptCards } from "./ConceptCards";
|
|
11
|
+
export type { ConceptCard } from "./ConceptCards";
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import React, { FunctionComponent, ReactElement } from "react";
|
|
2
|
+
import Icon from "../Icon/Icon";
|
|
3
|
+
import IconProp from "../../../Types/Icon/IconProp";
|
|
4
|
+
import Color from "../../../Types/Color";
|
|
5
|
+
|
|
6
|
+
export interface NumberedStep {
|
|
7
|
+
title: string;
|
|
8
|
+
description: string;
|
|
9
|
+
/** If provided, shows an icon instead of number */
|
|
10
|
+
icon?: IconProp | undefined;
|
|
11
|
+
/** Color for the step indicator */
|
|
12
|
+
color?: Color | undefined;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface ComponentProps {
|
|
16
|
+
steps: NumberedStep[];
|
|
17
|
+
/** Default color for steps */
|
|
18
|
+
defaultColor?: Color | undefined;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const NumberedSteps: FunctionComponent<ComponentProps> = (
|
|
22
|
+
props: ComponentProps,
|
|
23
|
+
): ReactElement => {
|
|
24
|
+
const defaultColor: Color = props.defaultColor || new Color("#6b7280"); // gray-500
|
|
25
|
+
|
|
26
|
+
return (
|
|
27
|
+
<div className="relative">
|
|
28
|
+
{props.steps.map((step: NumberedStep, index: number) => {
|
|
29
|
+
const color: Color = step.color || defaultColor;
|
|
30
|
+
const isLast: boolean = index === props.steps.length - 1;
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<div key={index} className="relative flex items-start pb-5 last:pb-0">
|
|
34
|
+
{/* Vertical line connecting steps */}
|
|
35
|
+
{!isLast && (
|
|
36
|
+
<div
|
|
37
|
+
className="absolute left-4 top-10 w-px bg-gray-200"
|
|
38
|
+
style={{ height: "calc(100% - 1.5rem)" }}
|
|
39
|
+
/>
|
|
40
|
+
)}
|
|
41
|
+
|
|
42
|
+
{/* Number/Icon indicator */}
|
|
43
|
+
<div
|
|
44
|
+
className="relative flex-shrink-0 w-8 h-8 rounded-full flex items-center justify-center border-2 bg-white"
|
|
45
|
+
style={{ borderColor: color.toString() }}
|
|
46
|
+
>
|
|
47
|
+
{step.icon ? (
|
|
48
|
+
<Icon
|
|
49
|
+
icon={step.icon}
|
|
50
|
+
className="h-4 w-4"
|
|
51
|
+
style={{ color: color.toString() }}
|
|
52
|
+
/>
|
|
53
|
+
) : (
|
|
54
|
+
<span
|
|
55
|
+
className="text-sm font-medium"
|
|
56
|
+
style={{ color: color.toString() }}
|
|
57
|
+
>
|
|
58
|
+
{index + 1}
|
|
59
|
+
</span>
|
|
60
|
+
)}
|
|
61
|
+
</div>
|
|
62
|
+
|
|
63
|
+
{/* Content */}
|
|
64
|
+
<div className="ml-4 flex-1 pt-0.5">
|
|
65
|
+
<h4 className="text-sm font-medium text-gray-900">
|
|
66
|
+
{step.title}
|
|
67
|
+
</h4>
|
|
68
|
+
<p className="text-sm text-gray-500 mt-0.5">{step.description}</p>
|
|
69
|
+
</div>
|
|
70
|
+
</div>
|
|
71
|
+
);
|
|
72
|
+
})}
|
|
73
|
+
</div>
|
|
74
|
+
);
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
export default NumberedSteps;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import React, { FunctionComponent, ReactElement } from "react";
|
|
2
|
+
import Icon from "../Icon/Icon";
|
|
3
|
+
import IconProp from "../../../Types/Icon/IconProp";
|
|
4
|
+
import Color from "../../../Types/Color";
|
|
5
|
+
|
|
6
|
+
export interface FlowStep {
|
|
7
|
+
title: string;
|
|
8
|
+
description: string;
|
|
9
|
+
icon: IconProp;
|
|
10
|
+
iconColor: Color;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface ComponentProps {
|
|
14
|
+
steps: FlowStep[];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const VerticalFlowSteps: FunctionComponent<ComponentProps> = (
|
|
18
|
+
props: ComponentProps,
|
|
19
|
+
): ReactElement => {
|
|
20
|
+
return (
|
|
21
|
+
<div className="relative">
|
|
22
|
+
{props.steps.map((step: FlowStep, index: number) => {
|
|
23
|
+
const isLast: boolean = index === props.steps.length - 1;
|
|
24
|
+
|
|
25
|
+
return (
|
|
26
|
+
<div key={index} className="relative flex items-start pb-6 last:pb-0">
|
|
27
|
+
{/* Vertical line connecting steps */}
|
|
28
|
+
{!isLast && (
|
|
29
|
+
<div
|
|
30
|
+
className="absolute left-4 top-10 w-px bg-gray-200"
|
|
31
|
+
style={{ height: "calc(100% - 1rem)" }}
|
|
32
|
+
/>
|
|
33
|
+
)}
|
|
34
|
+
|
|
35
|
+
{/* Icon */}
|
|
36
|
+
<div
|
|
37
|
+
className="relative flex-shrink-0 w-8 h-8 rounded-full flex items-center justify-center border border-gray-200 bg-white"
|
|
38
|
+
style={{ borderColor: `${step.iconColor.toString()}40` }}
|
|
39
|
+
>
|
|
40
|
+
<Icon
|
|
41
|
+
icon={step.icon}
|
|
42
|
+
className="h-4 w-4"
|
|
43
|
+
style={{ color: step.iconColor.toString() }}
|
|
44
|
+
/>
|
|
45
|
+
</div>
|
|
46
|
+
|
|
47
|
+
{/* Content */}
|
|
48
|
+
<div className="ml-4 flex-1">
|
|
49
|
+
<p className="text-sm font-medium text-gray-900">{step.title}</p>
|
|
50
|
+
<p className="text-sm text-gray-500 mt-0.5">{step.description}</p>
|
|
51
|
+
</div>
|
|
52
|
+
</div>
|
|
53
|
+
);
|
|
54
|
+
})}
|
|
55
|
+
</div>
|
|
56
|
+
);
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export default VerticalFlowSteps;
|
|
@@ -209,15 +209,19 @@ const FilterComponent: FilterComponentFunction = <T extends GenericObject>(
|
|
|
209
209
|
] as InBetween<Date>;
|
|
210
210
|
|
|
211
211
|
const shouldOnlyShowDate: boolean = data.filter.type === FieldType.Date;
|
|
212
|
+
const shouldShowSeconds: boolean =
|
|
213
|
+
data.filter.type === FieldType.DateTime;
|
|
212
214
|
|
|
213
215
|
if (
|
|
214
216
|
OneUptimeDate.getDateAsUserFriendlyLocalFormattedString(
|
|
215
217
|
startAndEndDates.startValue as Date,
|
|
216
218
|
shouldOnlyShowDate,
|
|
219
|
+
shouldShowSeconds,
|
|
217
220
|
) ===
|
|
218
221
|
OneUptimeDate.getDateAsUserFriendlyLocalFormattedString(
|
|
219
222
|
startAndEndDates.endValue as Date,
|
|
220
223
|
shouldOnlyShowDate,
|
|
224
|
+
shouldShowSeconds,
|
|
221
225
|
)
|
|
222
226
|
) {
|
|
223
227
|
return (
|
|
@@ -228,6 +232,7 @@ const FilterComponent: FilterComponentFunction = <T extends GenericObject>(
|
|
|
228
232
|
{OneUptimeDate.getDateAsUserFriendlyLocalFormattedString(
|
|
229
233
|
startAndEndDates.startValue as Date,
|
|
230
234
|
data.filter.type === FieldType.Date,
|
|
235
|
+
shouldShowSeconds,
|
|
231
236
|
)}
|
|
232
237
|
</span>{" "}
|
|
233
238
|
</div>
|
|
@@ -241,6 +246,7 @@ const FilterComponent: FilterComponentFunction = <T extends GenericObject>(
|
|
|
241
246
|
{OneUptimeDate.getDateAsUserFriendlyLocalFormattedString(
|
|
242
247
|
startAndEndDates.startValue as Date,
|
|
243
248
|
shouldOnlyShowDate,
|
|
249
|
+
shouldShowSeconds,
|
|
244
250
|
)}
|
|
245
251
|
</span>{" "}
|
|
246
252
|
and{" "}
|
|
@@ -248,6 +254,7 @@ const FilterComponent: FilterComponentFunction = <T extends GenericObject>(
|
|
|
248
254
|
{OneUptimeDate.getDateAsUserFriendlyLocalFormattedString(
|
|
249
255
|
startAndEndDates.endValue as Date,
|
|
250
256
|
shouldOnlyShowDate,
|
|
257
|
+
shouldShowSeconds,
|
|
251
258
|
)}
|
|
252
259
|
</span>{" "}
|
|
253
260
|
</div>
|
|
@@ -978,6 +978,16 @@ const Icon: FunctionComponent<ComponentProps> = ({
|
|
|
978
978
|
d="M2.25 6.75c0 8.284 6.716 15 15 15h2.25a2.25 2.25 0 002.25-2.25v-1.372c0-.516-.351-.966-.852-1.091l-4.423-1.106c-.44-.11-.902.055-1.173.417l-.97 1.293c-.282.376-.769.542-1.21.38a12.035 12.035 0 01-7.143-7.143c-.162-.441.004-.928.38-1.21l1.293-.97c.363-.271.527-.734.417-1.173L6.963 3.102a1.125 1.125 0 00-1.091-.852H4.5A2.25 2.25 0 002.25 4.5v2.25z"
|
|
979
979
|
/>,
|
|
980
980
|
);
|
|
981
|
+
} else if (icon === IconProp.IncomingCall) {
|
|
982
|
+
return getSvgWrapper(
|
|
983
|
+
<>
|
|
984
|
+
<path
|
|
985
|
+
strokeLinecap="round"
|
|
986
|
+
strokeLinejoin="round"
|
|
987
|
+
d="M14.25 9.75v-4.5m0 4.5h4.5m-4.5 0l6-6m-3 18c-8.284 0-15-6.716-15-15V4.5A2.25 2.25 0 014.5 2.25h1.372c.516 0 .966.351 1.091.852l1.106 4.423c.11.44-.054.902-.417 1.173l-1.293.97a1.062 1.062 0 00-.38 1.21 12.035 12.035 0 007.143 7.143c.441.162.928-.004 1.21-.38l.97-1.293a1.125 1.125 0 011.173-.417l4.423 1.106c.5.125.852.575.852 1.091V19.5a2.25 2.25 0 01-2.25 2.25h-2.25z"
|
|
988
|
+
/>
|
|
989
|
+
</>,
|
|
990
|
+
);
|
|
981
991
|
} else if (icon === IconProp.More) {
|
|
982
992
|
return getSvgWrapper(
|
|
983
993
|
<path
|
|
@@ -39,6 +39,7 @@ export interface ComponentProps {
|
|
|
39
39
|
outerDivClassName?: string | undefined;
|
|
40
40
|
autoFocus?: boolean | undefined;
|
|
41
41
|
disableSpellCheck?: boolean | undefined;
|
|
42
|
+
showSecondsForDateTime?: boolean | undefined;
|
|
42
43
|
}
|
|
43
44
|
|
|
44
45
|
const Input: FunctionComponent<ComponentProps> = (
|
|
@@ -188,6 +189,12 @@ const Input: FunctionComponent<ComponentProps> = (
|
|
|
188
189
|
}
|
|
189
190
|
readOnly={props.readOnly || props.disabled || false}
|
|
190
191
|
type={props.type || "text"}
|
|
192
|
+
step={
|
|
193
|
+
props.type === InputType.DATETIME_LOCAL &&
|
|
194
|
+
props.showSecondsForDateTime
|
|
195
|
+
? "1"
|
|
196
|
+
: undefined
|
|
197
|
+
}
|
|
191
198
|
placeholder={props.placeholder}
|
|
192
199
|
className={className}
|
|
193
200
|
onBlur={() => {
|