Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { AnalyticsFlowReportItem, AnalyticsRunsUsageItem, AnalyticsTimePeriod, apId, FlowVersionState, isNil, PlatformAnalyticsReport, PlatformId, ProjectLeaderboardItem, RunEnvironment, UserLeaderboardItem, UserWithMetaInformation } from '@activepieces/shared'
import { AnalyticsFlowReportItem, AnalyticsRunsUsageItem, AnalyticsTimePeriod, apId, FlowStatus, FlowVersionState, isNil, PlatformAnalyticsReport, PlatformId, ProjectLeaderboardItem, RunEnvironment, UserLeaderboardItem, UserWithMetaInformation } from '@activepieces/shared'
import dayjs from 'dayjs'
import { FastifyBaseLogger } from 'fastify'
import { IsNull } from 'typeorm'
Expand Down Expand Up @@ -138,6 +138,7 @@ async function listFlows(platformId: PlatformId, log: FastifyBaseLogger): Promis
cursorRequest: null,
versionState: FlowVersionState.DRAFT,
includeTriggerSource: false,
status: [FlowStatus.ENABLED],
})
const projects = await listProjects(platformId)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export function ProjectSelect({
variant="outline"
role="combobox"
aria-expanded={open}
className="w-auto gap-2 font-normal"
className="w-auto gap-2 font-normal h-8"
>
{selectedProject?.type === ProjectType.TEAM ? (
<Avatar
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ type TimeSavedFilterContentProps = {
unitMax: TimeUnit;
onCycleUnitMax: () => void;
onApply: () => void;
onClear?: () => void;
};

export function TimeSavedFilterContent({
Expand All @@ -29,7 +28,6 @@ export function TimeSavedFilterContent({
unitMax,
onCycleUnitMax,
onApply,
onClear,
}: TimeSavedFilterContentProps) {
return (
<div className="flex flex-col gap-3">
Expand Down Expand Up @@ -63,31 +61,23 @@ export function TimeSavedFilterContent({
placeholder="∞"
value={draftMax}
onChange={(e) => onMaxChange(e.target.value)}
className="pr-12"
className={draftMax ? 'pr-12' : ''}
/>
<button
type="button"
onClick={onCycleUnitMax}
className="absolute bg-accent px-1.5 py-0.5 rounded-sm right-2.5 top-1/2 -translate-y-1/2 text-xs text-muted-foreground hover:text-foreground cursor-pointer select-none"
>
{unitMax}
</button>
{draftMax && (
<button
type="button"
onClick={onCycleUnitMax}
className="absolute bg-accent px-1.5 py-0.5 rounded-sm right-2.5 top-1/2 -translate-y-1/2 text-xs text-muted-foreground hover:text-foreground cursor-pointer select-none"
>
{unitMax}
</button>
)}
</div>
</div>

<Button onClick={onApply} className="w-full mt-1">
{t('Apply')}
</Button>

{onClear && (
<button
type="button"
onClick={onClear}
className="w-full text-center text-sm text-primary hover:underline"
>
{t('Clear filter')}
</button>
)}
</div>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ export function EditTimeSavedPopover({
const [isOpen, setIsOpen] = useState(false);

const [hms, setHms] = useState({ hours: '', mins: '', secs: '' });
const minsRef = useRef<HTMLInputElement>(null);
const secsRef = useRef<HTMLInputElement>(null);

const handleOpenChange = (open: boolean) => {
if (open) {
Expand Down Expand Up @@ -81,73 +83,114 @@ export function EditTimeSavedPopover({
else if (e.key === 'Escape') setIsOpen(false);
};

const handleInputChange = (
const handleTimeInput = (
value: string,
field: keyof typeof hms,
max: number,
nextRef: React.RefObject<HTMLInputElement | null> | null,
) => {
const numericValue = value.replace(/\D/g, '');
const num = parseInt(numericValue, 10);
if (numericValue === '' || (num >= 0 && num <= max)) {

if (field === 'hours') {
const num = parseInt(numericValue, 10);
if (numericValue === '' || (num >= 0 && num <= max)) {
setHms((prev) => ({ ...prev, hours: numericValue }));
}
return;
}

if (numericValue === '') {
setHms((prev) => ({ ...prev, [field]: '' }));
return;
}

if (numericValue.length === 1) {
const digit = parseInt(numericValue, 10);
if (digit >= 6) {
setHms((prev) => ({ ...prev, [field]: '0' + numericValue }));
nextRef?.current?.focus();
nextRef?.current?.select();
return;
}
setHms((prev) => ({ ...prev, [field]: numericValue }));
return;
}

const clamped = numericValue.slice(0, 2);
const num = parseInt(clamped, 10);
if (num >= 0 && num <= max) {
setHms((prev) => ({ ...prev, [field]: clamped }));
nextRef?.current?.focus();
nextRef?.current?.select();
}
};

const padOnBlur = (field: 'mins' | 'secs') => {
setHms((prev) => {
const val = prev[field];
if (val.length === 1) {
return { ...prev, [field]: '0' + val };
}
return prev;
});
};

return (
<Popover open={isOpen} onOpenChange={handleOpenChange}>
<PopoverTrigger asChild>{children}</PopoverTrigger>
<PopoverContent className="w-[260px] p-4" align="start">
<div className="flex flex-col gap-4">
<div className="text-sm font-semibold">{t('Time Saved Per Run')}</div>

<div className="flex items-center rounded-md border border-input bg-background px-3 py-2 gap-1 focus-within:ring-1 focus-within:ring-ring">
<div className="flex items-center rounded-md border border-input bg-background px-3 py-1.5 gap-1 focus-within:ring-1 focus-within:ring-ring">
<div className="flex flex-col items-center gap-0.5 flex-1">
<input
type="text"
inputMode="numeric"
placeholder="hh"
value={hms.hours}
onChange={(e) => handleInputChange(e.target.value, 'hours', 99)}
onChange={(e) =>
handleTimeInput(e.target.value, 'hours', 1000, minsRef)
}
onKeyDown={handleKeyDown}
className="w-full text-center text-sm bg-transparent outline-none placeholder:text-muted-foreground/50"
maxLength={2}
maxLength={4}
autoFocus
/>
<span className="text-[10px] text-muted-foreground/60 leading-none">
{t('hh')}
</span>
</div>
<span className="text-muted-foreground font-medium pb-3">:</span>
<span className="text-muted-foreground font-medium">:</span>
<div className="flex flex-col items-center gap-0.5 flex-1">
<input
ref={minsRef}
type="text"
inputMode="numeric"
placeholder="mm"
value={hms.mins}
onChange={(e) => handleInputChange(e.target.value, 'mins', 59)}
onChange={(e) =>
handleTimeInput(e.target.value, 'mins', 59, secsRef)
}
onBlur={() => padOnBlur('mins')}
onKeyDown={handleKeyDown}
className="w-full text-center text-sm bg-transparent outline-none placeholder:text-muted-foreground/50"
maxLength={2}
/>
<span className="text-[10px] text-muted-foreground/60 leading-none">
{t('mm')}
</span>
</div>
<span className="text-muted-foreground font-medium pb-3">:</span>
<span className="text-muted-foreground font-medium">:</span>
<div className="flex flex-col items-center gap-0.5 flex-1">
<input
ref={secsRef}
type="text"
inputMode="numeric"
placeholder="ss"
value={hms.secs}
onChange={(e) => handleInputChange(e.target.value, 'secs', 59)}
onChange={(e) =>
handleTimeInput(e.target.value, 'secs', 59, null)
}
onBlur={() => padOnBlur('secs')}
onKeyDown={handleKeyDown}
className="w-full text-center text-sm bg-transparent outline-none placeholder:text-muted-foreground/50"
maxLength={2}
/>
<span className="text-[10px] text-muted-foreground/60 leading-none">
{t('ss')}
</span>
</div>
</div>

Expand Down
29 changes: 7 additions & 22 deletions packages/web/src/app/routes/impact/details/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -139,11 +139,12 @@ export function FlowsDetails({
<Tooltip>
<TooltipTrigger asChild>
<div className="flex items-center gap-1.5 text-muted-foreground cursor-not-allowed">
<span>{displayValue ?? t('Not set')}</span>
<Plus className="h-3.5 w-3.5" />
<span>{t('Add Estimated Time')}</span>
</div>
</TooltipTrigger>
<TooltipContent side="top">
{t("You don't have permission to edit this flow")}
{t("You don't have permission to add")}
</TooltipContent>
</Tooltip>
);
Expand All @@ -158,10 +159,10 @@ export function FlowsDetails({
flowId={row.original.flowId}
currentValue={timeSavedPerRun}
>
<button className="flex items-center gap-1 px-1.5 py-0.5 rounded text-xs text-primary hover:bg-primary/10">
<Pencil className="h-3 w-3" />
<Button variant="link" size="xs">
<Pencil className="size-3! mr-1" />
<span>{t('Edit')}</span>
</button>
</Button>
</EditTimeSavedPopover>
</span>
</div>
Expand Down Expand Up @@ -231,12 +232,7 @@ export function FlowsDetails({

if (userHasAccess) {
return (
<div
className="flex items-center gap-1.5 text-foreground hover:underline cursor-pointer"
onClick={() =>
window.open(`/projects/${row.original.projectId}`, '_blank')
}
>
<div className="flex items-center gap-1.5 text-foreground">
{projectAvatar}
{projectName}
</div>
Expand Down Expand Up @@ -283,16 +279,6 @@ export function FlowsDetails({
<TimeSavedFilter filters={filters} />
<OwnerFilter filters={filters} />

{filters.hasActiveFilters && (
<button
onClick={filters.clearAllFilters}
className="flex items-center gap-1 text-sm text-primary hover:underline"
>
<X className="h-3.5 w-3.5" />
{t('Clear')}
</button>
)}

<div className="flex-1" />

<Tooltip>
Expand Down Expand Up @@ -385,7 +371,6 @@ function TimeSavedFilter({ filters }: { filters: FiltersReturn }) {
unitMax={filters.draftTimeSaved.unitMax}
onCycleUnitMax={filters.cycleDraftTimeUnitMax}
onApply={filters.applyTimeSavedFilter}
onClear={filters.clearTimeSavedFilter}
/>
</PopoverContent>
</Popover>
Expand Down
6 changes: 3 additions & 3 deletions packages/web/src/app/routes/impact/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -106,14 +106,14 @@ export default function ImpactPage() {
<Info className="h-4 w-4 text-muted-foreground cursor-help" />
</TooltipTrigger>
<TooltipContent>
{t('View impact analytics and metrics')}
{t('View impact analytics and metrics for the active flows.')}
</TooltipContent>
</Tooltip>
</div>
</div>

<div className="flex items-center gap-3">
<div className="flex items-center gap-2 px-3 py-1.5 border border-dashed rounded-md text-sm text-muted-foreground">
<div className="flex items-center gap-2 px-3 h-8 py-1 border border-dashed rounded-md text-sm text-muted-foreground">
<span>
{t('Updated')} {dayjs(data?.updated).format('MMM DD, hh:mm A')} —{' '}
{t('Refreshes daily')}
Expand Down Expand Up @@ -147,7 +147,7 @@ export default function ImpactPage() {
value={selectedTimePeriod}
onValueChange={handleTimePeriodChange}
>
<SelectTrigger className="w-auto gap-2">
<SelectTrigger className="w-auto gap-2 h-8">
<Calendar className="h-4 w-4" />
<SelectValue />
</SelectTrigger>
Expand Down
4 changes: 2 additions & 2 deletions packages/web/src/app/routes/impact/lib/impact-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ export const secondsToHMS = (
const s = totalSeconds % 60;
return {
hours: h > 0 ? h.toString() : '',
mins: m > 0 || h > 0 ? m.toString() : '',
secs: s > 0 || m > 0 || h > 0 ? s.toString() : '',
mins: m > 0 || h > 0 ? m.toString().padStart(2, '0') : '',
secs: s > 0 || m > 0 || h > 0 ? s.toString().padStart(2, '0') : '',
};
};

Expand Down
22 changes: 16 additions & 6 deletions packages/web/src/app/routes/impact/lib/use-details-filters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,16 +58,26 @@ export function useDetailsFilters(

const cycleDraftTimeUnitMin = () => {
const idx = TIME_UNITS.indexOf(draftTimeSaved.unitMin);
updateDraftTimeSaved({
unitMin: TIME_UNITS[(idx + 1) % TIME_UNITS.length],
});
const newMinUnit = TIME_UNITS[(idx + 1) % TIME_UNITS.length];
const newMinIdx = TIME_UNITS.indexOf(newMinUnit);
const maxIdx = TIME_UNITS.indexOf(draftTimeSaved.unitMax);
if (newMinIdx > maxIdx) {
updateDraftTimeSaved({ unitMin: newMinUnit, unitMax: newMinUnit });
} else {
updateDraftTimeSaved({ unitMin: newMinUnit });
}
};

const cycleDraftTimeUnitMax = () => {
const idx = TIME_UNITS.indexOf(draftTimeSaved.unitMax);
updateDraftTimeSaved({
unitMax: TIME_UNITS[(idx + 1) % TIME_UNITS.length],
});
const newMaxUnit = TIME_UNITS[(idx + 1) % TIME_UNITS.length];
const newMaxIdx = TIME_UNITS.indexOf(newMaxUnit);
const minIdx = TIME_UNITS.indexOf(draftTimeSaved.unitMin);
if (newMaxIdx < minIdx) {
updateDraftTimeSaved({ unitMax: newMaxUnit, unitMin: newMaxUnit });
} else {
updateDraftTimeSaved({ unitMax: newMaxUnit });
}
};

const handleTimeSavedPopoverOpen = (open: boolean) => {
Expand Down
Loading
Loading