Skip to content

Commit

Permalink
Constraint status improvements and fixes (#1107)
Browse files Browse the repository at this point in the history
* Modify status text and change Incomplete color to blue since it is used for indeterminate loading
* Add new constraint stores to better track different aspects of constraint status
* Use indeterminate progress for expansion and scheduling goal panel status
* Indeterminate Status icon support
* Pass indeterminate prop through PanelHeaderActions
* Improvements and bug fixes to constraint status and display
* Move status enums to enum file
  • Loading branch information
AaronPlave authored Feb 5, 2024
1 parent 84f6e61 commit dff98cf
Show file tree
Hide file tree
Showing 21 changed files with 250 additions and 61 deletions.
3 changes: 2 additions & 1 deletion src/components/app/NavButton.svelte
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<script lang="ts">
import { createEventDispatcher } from 'svelte';
import { getColorForStatus, type Status } from '../../utilities/status';
import type { Status } from '../../enums/status';
import { getColorForStatus } from '../../utilities/status';
export let selected: boolean = false;
export let status: Status | null = null;
Expand Down
30 changes: 29 additions & 1 deletion src/components/constraints/ConstraintListItem.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import VisibleShowIcon from '@nasa-jpl/stellar/icons/visible_show.svg?component';
import WarningIcon from '@nasa-jpl/stellar/icons/warning.svg?component';
import { createEventDispatcher } from 'svelte';
import { Status } from '../../enums/status';
import type { User } from '../../types/app';
import type { Constraint, ConstraintResponse } from '../../types/constraint';
import type { Plan } from '../../types/plan';
Expand All @@ -18,6 +19,7 @@
import Collapse from '../Collapse.svelte';
import ContextMenuHeader from '../context-menu/ContextMenuHeader.svelte';
import ContextMenuItem from '../context-menu/ContextMenuItem.svelte';
import StatusBadge from '../ui/StatusBadge.svelte';
import ConstraintViolationButton from './ConstraintViolationButton.svelte';
export let constraint: Constraint;
Expand Down Expand Up @@ -58,6 +60,10 @@
<div class="no-violations" use:tooltip={{ content: 'No Violations', placement: 'top' }}>
<CheckmarkIcon />
</div>
{:else}
<span class="unchecked">
<StatusBadge status={Status.Unchecked} />
</span>
{/if}
<button
use:tooltip={{ content: visible ? 'Hide' : 'Show', placement: 'top' }}
Expand Down Expand Up @@ -97,6 +103,16 @@
{/if}
</Collapse>

{#if !success && constraintResponse?.errors}
<Collapse title="Errors" defaultExpanded={false}>
<div class="errors">
{#each constraintResponse?.errors as error}
<div class="st-typography-body">{error.message}</div>
{/each}
</div>
</Collapse>
{/if}

<svelte:fragment slot="contextMenuContent">
<ContextMenuHeader>Actions</ContextMenuHeader>
<ContextMenuItem
Expand Down Expand Up @@ -149,11 +165,16 @@
padding: 0px 6px;
}
.violations {
.violations,
.errors {
display: flex;
flex-direction: column;
}
.errors {
gap: 8px;
}
.no-violations {
align-items: center;
color: var(--st-success-green);
Expand All @@ -171,4 +192,11 @@
justify-content: center;
width: 20px;
}
.unchecked {
display: flex;
flex-shrink: 0;
justify-content: center;
width: 20px;
}
</style>
33 changes: 23 additions & 10 deletions src/components/constraints/ConstraintsPanel.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,19 @@
import VisibleHideIcon from '@nasa-jpl/stellar/icons/visible_hide.svg?component';
import VisibleShowIcon from '@nasa-jpl/stellar/icons/visible_show.svg?component';
import { PlanStatusMessages } from '../../enums/planStatusMessages';
import { Status } from '../../enums/status';
import {
checkConstraintsStatus,
constraintResponseMap,
constraintVisibilityMap,
constraints,
constraintsStatus,
setAllConstraintsVisible,
setConstraintVisibility,
} from '../../stores/constraints';
import { field } from '../../stores/form';
import { plan, planReadOnly, viewTimeRange } from '../../stores/plan';
import { simulationStatus } from '../../stores/simulation';
import type { User } from '../../types/app';
import type { Constraint, ConstraintResponse } from '../../types/constraint';
import type { FieldStore } from '../../types/form';
Expand Down Expand Up @@ -50,7 +53,7 @@
let startTimeDoyField: FieldStore<string>;
let showFilters: boolean = false;
let showConstraintsWithNoViolations: boolean = true;
let filteredConstraintResponseMap: Record<Constraint['id'], ConstraintResponse> = {};
let constraintToConstraintResponseMap: Record<Constraint['id'], ConstraintResponse> = {};
$: startTimeDoy = $plan?.start_time_doy || '';
$: startTimeDoyField = field<string>(startTimeDoy, [required, timestamp]);
Expand All @@ -60,11 +63,11 @@
$: endTimeMs = getUnixEpochTime(endTimeDoy);
$: if ($constraints && $constraintResponseMap && startTimeMs && endTimeMs) {
filteredConstraintResponseMap = {};
constraintToConstraintResponseMap = {};
$constraints.forEach(constraint => {
const constraintResponse = $constraintResponseMap[constraint.id];
if (constraintResponse) {
filteredConstraintResponseMap[constraint.id] = {
constraintToConstraintResponseMap[constraint.id] = {
constraintId: constraintResponse.constraintId,
constraintName: constraintResponse.constraintName,
errors: constraintResponse.errors,
Expand All @@ -86,16 +89,20 @@
$: filteredConstraints = filterConstraints(
$constraints,
filteredConstraintResponseMap,
constraintToConstraintResponseMap,
filterText,
showConstraintsWithNoViolations,
);
$: filteredConstraintResponses = Object.values(constraintToConstraintResponseMap).filter(r =>
filteredConstraints.find(c => c.id === r.constraintId),
);
$: totalViolationCount = getViolationCount(Object.values($constraintResponseMap));
$: filteredViolationCount = getViolationCount(Object.values(filteredConstraintResponseMap));
$: filteredViolationCount = getViolationCount(Object.values(filteredConstraintResponses));
function filterConstraints(
constraints: Constraint[],
filteredConstraintResponseMap: Record<Constraint['id'], ConstraintResponse>,
constraintToConstraintResponseMap: Record<Constraint['id'], ConstraintResponse>,
filterText: string,
showConstraintsWithNoViolations: boolean,
) {
Expand All @@ -106,7 +113,7 @@
return false;
}
const constraintResponse = filteredConstraintResponseMap[constraint.id];
const constraintResponse = constraintToConstraintResponseMap[constraint.id];
// Always show constraints with no violations
if (!constraintResponse?.results.violations?.length) {
return showConstraintsWithNoViolations;
Expand All @@ -118,7 +125,7 @@
function getViolationCount(constraintResponse: ConstraintResponse[]) {
return constraintResponse.reduce((count, constraintResponse) => {
return constraintResponse.results.violations ? constraintResponse.results.violations.length + count : 0;
return constraintResponse.results.violations ? constraintResponse.results.violations.length + count : count;
}, 0);
}
Expand Down Expand Up @@ -170,8 +177,10 @@
<Panel>
<svelte:fragment slot="header">
<GridMenu {gridSection} title="Constraints" />
<PanelHeaderActions status={$checkConstraintsStatus}>
<PanelHeaderActions status={$constraintsStatus} indeterminate>
<PanelHeaderActionButton
disabled={$simulationStatus !== Status.Complete}
tooltipContent={$simulationStatus !== Status.Complete ? 'Completed simulation required' : ''}
title="Check Constraints"
on:click={() => $plan && effects.checkConstraints($plan, user)}
use={[
Expand Down Expand Up @@ -287,7 +296,7 @@
{#each filteredConstraints as constraint}
<ConstraintListItem
{constraint}
constraintResponse={filteredConstraintResponseMap[constraint.id]}
constraintResponse={constraintToConstraintResponseMap[constraint.id]}
hasDeletePermission={$plan ? featurePermissions.constraints.canDelete(user, $plan) : false}
hasEditPermission={$plan ? featurePermissions.constraints.canUpdate(user, $plan) : false}
plan={$plan}
Expand Down Expand Up @@ -331,6 +340,10 @@
gap: 4px;
}
.filter-label :global(svg) {
flex-shrink: 0;
}
.checkbox-container {
align-items: center;
display: flex;
Expand Down
2 changes: 1 addition & 1 deletion src/components/expansion/ExpansionPanel.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@
<Panel padBody={false}>
<svelte:fragment slot="header">
<GridMenu {gridSection} title="Expansion" />
<PanelHeaderActions status={$planExpansionStatus}>
<PanelHeaderActions status={$planExpansionStatus} indeterminate>
<PanelHeaderActionButton
title="Expand"
showLabel
Expand Down
2 changes: 1 addition & 1 deletion src/components/menus/ActivityStatusMenu.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
<script lang="ts">
import WaterfallIcon from '@nasa-jpl/stellar/icons/waterfall.svg?component';
import { createEventDispatcher } from 'svelte';
import { Status } from '../../enums/status';
import type { ActivityDirectiveValidationStatus } from '../../types/activity';
import type { ActivityErrorCounts } from '../../types/errors';
import { Status } from '../../utilities/status';
import PlanNavButton from '../plan/PlanNavButton.svelte';
import ActivityErrorsRollup from '../ui/ActivityErrorsRollup.svelte';
Expand Down
2 changes: 1 addition & 1 deletion src/components/menus/ViewMenu.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@
import ViewGridRightPanelSplitEmpty from '@nasa-jpl/stellar/icons/view_grid_right_panel_split_empty.svg?component';
import ViewGridRightPanelSplitFilled from '@nasa-jpl/stellar/icons/view_grid_right_panel_split_filled.svg?component';
import { createEventDispatcher } from 'svelte';
import { Status } from '../../enums/status';
import { view, viewIsModified } from '../../stores/views';
import type { User } from '../../types/app';
import type { ViewToggleType } from '../../types/view';
import { showSavedViewsModal } from '../../utilities/modal';
import { permissionHandler } from '../../utilities/permissionHandler';
import { Status } from '../../utilities/status';
import { downloadView } from '../../utilities/view';
import PlanNavButton from '../plan/PlanNavButton.svelte';
import ToggleableIcon from '../ui/ToggleableIcon.svelte';
Expand Down
10 changes: 6 additions & 4 deletions src/components/plan/PlanNavButton.svelte
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
<script lang="ts">
import PlayIcon from '@nasa-jpl/stellar/icons/play.svg?component';
import type { Status } from '../../enums/status';
import { permissionHandler } from '../../utilities/permissionHandler';
import type { Status } from '../../utilities/status';
import { getHumanReadableStatus } from '../../utilities/simulation';
import { tooltip } from '../../utilities/tooltip';
import Menu from '../menus/Menu.svelte';
import MenuHeader from '../menus/MenuHeader.svelte';
Expand All @@ -11,6 +12,7 @@
export let buttonTooltipContent: string = '';
export let disabled: boolean = false;
export let hasPermission: boolean = true;
export let indeterminate: boolean = false;
export let menuTitle: string = '';
export let permissionError: string | undefined = undefined;
export let status: Status | null = null;
Expand All @@ -33,7 +35,7 @@
<slot />
<span class="nav-button-status">
{#if status}
<StatusBadge badgeText={statusBadgeText} {progress} {status} showTooltip={false} />
<StatusBadge badgeText={statusBadgeText} {indeterminate} {progress} {status} showTooltip={false} />
{/if}
</span>
</div>
Expand All @@ -49,8 +51,8 @@
<div class="menu-body">
{#if status && showStatusInMenu}
<div class="status-row st-typography-body">
<StatusBadge {status} {progress} showTooltip={false} />
{statusText || status}
<StatusBadge {status} {indeterminate} {progress} showTooltip={false} />
{statusText || getHumanReadableStatus(status)}
</div>
{/if}
<div class="menu-metadata st-typography-body">
Expand Down
2 changes: 1 addition & 1 deletion src/components/scheduling/SchedulingGoalsPanel.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
<Panel>
<svelte:fragment slot="header">
<GridMenu {gridSection} title="Scheduling Goals" />
<PanelHeaderActions status={$schedulingStatus}>
<PanelHeaderActions status={$schedulingStatus} indeterminate>
<PanelHeaderActionButton
title="Analyze"
on:click={() => effects.schedule(true, $plan, user)}
Expand Down
6 changes: 3 additions & 3 deletions src/components/simulation/SimulationHistoryDataset.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,19 @@
<script lang="ts">
import CancelIcon from '@nasa-jpl/stellar/icons/prohibited.svg?component';
import { createEventDispatcher } from 'svelte';
import { Status } from '../../enums/status';
import { planReadOnly } from '../../stores/plan';
import type { SimulationDataset } from '../../types/simulation';
import { hexToRgba } from '../../utilities/color';
import {
formatSimulationQueuePosition,
getHumanReadableSimulationStatus,
getHumanReadableStatus,
getSimulationExtent,
getSimulationProgress,
getSimulationProgressColor,
getSimulationStatus,
getSimulationTimestamp,
} from '../../utilities/simulation';
import { Status } from '../../utilities/status';
import { getDoyTime, getUnixEpochTimeFromInterval } from '../../utilities/time';
import { tooltip } from '../../utilities/tooltip';
import Card from '../ui/Card.svelte';
Expand Down Expand Up @@ -108,7 +108,7 @@
{#if status === Status.Pending}
{formatSimulationQueuePosition(queuePosition)}
{:else}
{getHumanReadableSimulationStatus(status)}
{getHumanReadableStatus(status)}
{/if}
</div>
{#if status === Status.Pending || status === Status.Incomplete}
Expand Down
2 changes: 1 addition & 1 deletion src/components/simulation/SimulationPanel.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import PlanRightArrow from '@nasa-jpl/stellar/icons/plan_with_right_arrow.svg?component';
import { PlanStatusMessages } from '../../enums/planStatusMessages';
import { SearchParameters } from '../../enums/searchParameters';
import { Status } from '../../enums/status';
import { field } from '../../stores/form';
import { plan, planEndTimeMs, planReadOnly, planStartTimeMs } from '../../stores/plan';
import { planSnapshot } from '../../stores/planSnapshots';
Expand Down Expand Up @@ -33,7 +34,6 @@
import { permissionHandler } from '../../utilities/permissionHandler';
import { featurePermissions } from '../../utilities/permissions';
import { getSimulationQueuePosition } from '../../utilities/simulation';
import { Status } from '../../utilities/status';
import { getDoyTime } from '../../utilities/time';
import { required, timestamp, validateEndTime, validateStartTime } from '../../utilities/validators';
import Collapse from '../Collapse.svelte';
Expand Down
5 changes: 3 additions & 2 deletions src/components/ui/PanelHeaderActions.svelte
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
<script lang="ts">
import type { Status } from '../../utilities/status';
import type { Status } from '../../enums/status';
import StatusBadge from './StatusBadge.svelte';
export let status: Status | null = null;
export let indeterminate: boolean = false;
</script>

<span class="header-actions">
{#if status}
<StatusBadge {status} />
<StatusBadge {status} {indeterminate} />
{/if}
<slot />
</span>
Expand Down
Loading

0 comments on commit dff98cf

Please sign in to comment.