Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UI loading indicators part 1 #1589

Merged
merged 37 commits into from
Feb 4, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
f16e80a
Add loading text component
AaronPlave Jan 3, 2025
735b930
Add data grid loading skeleton and loading prop
AaronPlave Jan 3, 2025
3265b6f
Improve loading indication for several stores and requests
AaronPlave Jan 3, 2025
e083b5f
Loading style fix
AaronPlave Jan 15, 2025
76138bf
Constraint runs loading improvements
AaronPlave Jan 15, 2025
927ead5
Fix initial navbar jerkiness on page load
AaronPlave Jan 15, 2025
4b9fad1
DataGrid loading improvements
AaronPlave Jan 15, 2025
73633ab
Fix simulation dataset id usage
AaronPlave Jan 15, 2025
5744eb4
Loading for constraints
AaronPlave Jan 16, 2025
5ac4814
Allow customization of loading message
AaronPlave Jan 16, 2025
23d819d
Bug fix table tag cell rendering
AaronPlave Jan 16, 2025
0a125e4
Make schedulingConditionResponses and schedulingGoalResponses nullabl…
AaronPlave Jan 16, 2025
6a41ce1
Initial span loading tracking and indication
AaronPlave Jan 17, 2025
9fc85e0
Timeline histogram loading state
AaronPlave Jan 17, 2025
46ee633
Scheduling goal and condition loading states within a plan
AaronPlave Jan 17, 2025
f91a27a
Activity layer loading indicator fix
AaronPlave Jan 22, 2025
345e95a
Style fix
AaronPlave Jan 22, 2025
9316d0a
Scheduling goal and condition loading refactor and improvements
AaronPlave Jan 22, 2025
f5a89b5
Style plugin loading message
AaronPlave Jan 22, 2025
4505a31
Revert change
AaronPlave Jan 22, 2025
078a10f
Constraint loading improvements
AaronPlave Jan 22, 2025
b20212f
Fixes
AaronPlave Jan 22, 2025
30ca747
Show loading indicator in timeline editor while view and selected tim…
AaronPlave Jan 22, 2025
a33752b
Improve timeline editor loading by setting default timeline to be 0
AaronPlave Jan 22, 2025
0c018e5
Sim event loading
AaronPlave Jan 22, 2025
c24a411
Loading for plan snapshots
AaronPlave Jan 22, 2025
3f9cd55
Refactoring
AaronPlave Jan 28, 2025
939cb2f
Refactor
AaronPlave Jan 28, 2025
99416f7
Fix
AaronPlave Jan 28, 2025
155c23f
Refactor
AaronPlave Jan 28, 2025
4793678
Refactor
AaronPlave Jan 28, 2025
129411e
view and user loading stores
AaronPlave Jan 28, 2025
672cc9c
Alphabetize
AaronPlave Jan 28, 2025
cade87e
update GetPlansAndModels query to match ModelSlim
AaronPlave Jan 28, 2025
e595ad5
TODO
AaronPlave Jan 29, 2025
4e1405a
Clean
AaronPlave Jan 29, 2025
5030478
Remove comment
AaronPlave Feb 4, 2025
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
16 changes: 16 additions & 0 deletions src/components/Loading.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<div class="st-typography-label loading">
{#if $$slots.default}
<slot />
{:else}
Loading...
{/if}
</div>

<style>
.loading {
display: flex;
flex-direction: column;
user-select: none;
width: 100%;
}
</style>
6 changes: 3 additions & 3 deletions src/components/activity/ActivityDecomposition.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
export let expanded = true;
export let rootSpanId: SpanId | null = null;
export let selectedSpanId: SpanId | null = null;
export let spansMap: SpansMap = {};
export let spansMap: SpansMap | null = {};
export let spanUtilityMaps: SpanUtilityMaps;
export let childPageSize: number = 25;

Expand All @@ -31,7 +31,7 @@
let buttonClass: string = '';
let childIdsInView: SpanId[] = [];

$: span = rootSpanId !== null ? spansMap[rootSpanId] : null;
$: span = rootSpanId !== null && spansMap !== null ? spansMap[rootSpanId] : null;
$: isRoot = span ? !span.parent_id : true;
$: type = span?.type || '';
$: childIds = span !== null ? spanUtilityMaps?.spanIdToChildIdsMap[span?.span_id] || [] : [];
Expand Down Expand Up @@ -76,7 +76,7 @@
</span>
</div>

{#if hasChildren && expanded}
{#if hasChildren && expanded && spansMap}
<ul>
{#each childIdsInView as childId}
<li>
Expand Down
25 changes: 13 additions & 12 deletions src/components/activity/ActivityDirectivesTable.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,29 @@

<script lang="ts">
import type { ColDef, ColumnState, ICellRendererParams } from 'ag-grid-community';
import { createEventDispatcher } from 'svelte';
import { PlanStatusMessages } from '../../enums/planStatusMessages';
import type { ActivityDirective, ActivityDirectiveId } from '../../types/activity';
import type { User } from '../../types/app';
import type { DataGridColumnDef } from '../../types/data-grid';
import type { ActivityErrorCounts, ActivityErrorRollup } from '../../types/errors';
import type { Plan } from '../../types/plan';
import {
canPasteActivityDirectivesFromClipboard,
copyActivityDirectivesToClipboard,
getActivityDirectivesToPaste,
getPasteActivityDirectivesText,
} from '../../utilities/activities';
import effects from '../../utilities/effects';
import { featurePermissions } from '../../utilities/permissions';
import ContextMenuItem from '../context-menu/ContextMenuItem.svelte';
import ContextMenuSeparator from '../context-menu/ContextMenuSeparator.svelte';
import ActivityErrorsRollup from '../ui/ActivityErrorsRollup.svelte';
import BulkActionDataGrid from '../ui/DataGrid/BulkActionDataGrid.svelte';
import type DataGrid from '../ui/DataGrid/DataGrid.svelte';
import DataGridActions from '../ui/DataGrid/DataGridActions.svelte';
import ContextMenuItem from '../context-menu/ContextMenuItem.svelte';
import ContextMenuSeparator from '../context-menu/ContextMenuSeparator.svelte';
import { createEventDispatcher } from 'svelte';
import {
canPasteActivityDirectivesFromClipboard,
copyActivityDirectivesToClipboard,
getPasteActivityDirectivesText,
getActivityDirectivesToPaste,
} from '../../utilities/activities';

export let activityDirectives: ActivityDirective[] = [];
export let activityDirectives: ActivityDirective[] | null = null;
export let activityDirectiveErrorRollupsMap: Record<ActivityDirectiveId, ActivityErrorRollup> | undefined = undefined;
export let columnDefs: ColDef[];
export let columnStates: ColumnState[] = [];
Expand Down Expand Up @@ -62,7 +62,7 @@
$: hasCreatePermission =
plan !== null ? featurePermissions.activityDirective.canCreate(user, plan) && !planReadOnly : false;

$: activityDirectivesWithErrorCounts = activityDirectives.map(activityDirective => ({
$: activityDirectivesWithErrorCounts = (activityDirectives || []).map(activityDirective => ({
...activityDirective,
errorCounts: activityDirectiveErrorRollupsMap?.[activityDirective.id]?.errorCounts,
}));
Expand Down Expand Up @@ -154,7 +154,7 @@

function scrollTimelineToActivityDirective() {
const directiveId = bulkSelectedActivityDirectiveIds.length > 0 && bulkSelectedActivityDirectiveIds[0];
const directive = activityDirectives.find(item => item.id === directiveId) ?? null;
const directive = (activityDirectives || []).find(item => item.id === directiveId) ?? null;
if (directive?.start_time_ms !== undefined && directive?.start_time_ms !== null) {
dispatch('scrollTimelineToTime', directive.start_time_ms);
}
Expand Down Expand Up @@ -188,6 +188,7 @@
columnDefs={completeColumnDefs}
{columnStates}
{getRowId}
loading={!activityDirectives}
{hasDeletePermission}
hasDeletePermissionError={planReadOnly ? PlanStatusMessages.READ_ONLY : undefined}
items={activityDirectivesWithErrorCounts}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,6 @@
resizable: true,
sortable: false,
width: 220,
wrapText: true,
},
type: {
field: 'type',
Expand Down Expand Up @@ -428,7 +427,7 @@
<ActivityDirectivesTable
bind:dataGrid
bind:selectedActivityDirectiveId={$selectedActivityDirectiveId}
activityDirectives={Object.values($activityDirectivesMap)}
activityDirectives={$activityDirectivesMap ? Object.values($activityDirectivesMap) : null}
activityDirectiveErrorRollupsMap={$activityErrorRollupsMap}
{filterExpression}
columnDefs={derivedColumnDefs ?? []}
Expand Down
8 changes: 4 additions & 4 deletions src/components/activity/ActivityFormPanel.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,14 @@
previewRevision = undefined;
}

$: if ($selectedActivityDirective) {
$: if ($selectedActivityDirective && $spansMap) {
directiveRootSpanId =
$spansMap[$spanUtilityMaps.directiveIdToSpanIdMap[$selectedActivityDirective.id]]?.span_id ?? null;
} else {
directiveRootSpanId = null;
}

$: if ($selectedSpan) {
$: if ($selectedSpan && $spansMap) {
const rootSpan = getSpanRootParent($spansMap, $selectedSpan.span_id);
if (rootSpan) {
spanDirectiveId = $spanUtilityMaps.spanIdToDirectiveIdMap[rootSpan.span_id] ?? null;
Expand Down Expand Up @@ -203,7 +203,7 @@
{#if $selectedActivityDirective && $plan !== null && viewingActivityDirectiveChangelog}
<ActivityDirectiveChangelog
activityDirective={$selectedActivityDirective}
activityDirectivesMap={$activityDirectivesMap}
activityDirectivesMap={$activityDirectivesMap || {}}
activityTypes={$activityTypes}
modelId={$modelId}
planStartTimeYmd={$plan.start_time}
Expand All @@ -213,7 +213,7 @@
/>
{:else if $selectedActivityDirective && $plan !== null}
<ActivityDirectiveForm
activityDirectivesMap={$activityDirectivesMap}
activityDirectivesMap={$activityDirectivesMap || {}}
activityDirective={$selectedActivityDirective}
activityMetadataDefinitions={$activityMetadataDefinitions}
activityTypes={$activityTypes}
Expand Down
4 changes: 2 additions & 2 deletions src/components/activity/ActivitySpanForm.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
export let modelId: number;
export let simulationDatasetId: number = -1;
export let span: Span;
export let spansMap: SpansMap = {};
export let spansMap: SpansMap | null = {};
export let spanUtilityMaps: SpanUtilityMaps;
export let user: User | null;

Expand All @@ -40,7 +40,7 @@
let startTime: string;

$: activityType = (activityTypes ?? []).find(({ name: activityTypeName }) => span.type === activityTypeName) ?? null;
$: rootSpan = getSpanRootParent(spansMap, span.span_id);
$: rootSpan = !spansMap ? null : getSpanRootParent(spansMap, span.span_id);
$: rootSpanHasChildren = (rootSpan && spanUtilityMaps.spanIdToChildIdsMap[rootSpan.span_id]?.length > 0) ?? false;

$: startTime = formatDate(new Date(span.startMs), $plugins.time.primary.format);
Expand Down
6 changes: 4 additions & 2 deletions src/components/activity/ActivitySpansTable.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@
export let columnDefs: ColDef[];
export let columnStates: ColumnState[] = [];
export let dataGrid: DataGrid<Span> | undefined = undefined;
export let loading: boolean = false;
export let selectedSpanId: SpanId | null = null;
export let spans: Span[] = [];
export let spans: Span[] | null | undefined = undefined;
export let filterExpression: string = '';

let selectedItemIds: RowId[] = [];
Expand All @@ -36,7 +37,8 @@
{filterExpression}
{getRowId}
useCustomContextMenu
rowData={spans}
rowData={spans || []}
{loading}
rowSelection="single"
scrollToSelection={true}
suppressDragLeaveHidesColumns={false}
Expand Down
3 changes: 2 additions & 1 deletion src/components/activity/ActivitySpansTablePanel.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import { InvalidDate } from '../../constants/time';
import { selectActivity } from '../../stores/activities';
import { plugins } from '../../stores/plugins';
import { selectedSpanId, spans } from '../../stores/simulation';
import { initialSpansLoading, selectedSpanId, spans } from '../../stores/simulation';
import { view, viewTogglePanel, viewUpdateActivitySpansTable } from '../../stores/views';
import type { Span } from '../../types/simulation';
import type { AutoSizeColumns, ViewGridSection, ViewTable } from '../../types/view';
Expand Down Expand Up @@ -333,6 +333,7 @@
columnDefs={derivedColumnDefs ?? []}
columnStates={activitySpansTable?.columnStates}
{filterExpression}
loading={$initialSpansLoading}
spans={$spans}
on:columnMoved={onColumnMoved}
on:columnPinned={onColumnPinned}
Expand Down
2 changes: 1 addition & 1 deletion src/components/activity/TimelineItemsPanel.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
box-shadow: 0px -1px 0px inset var(--st-gray-20);
}

:global(button.timeline-items-tab.selected) {
:global(.timeline-items-tabs .timeline-items-tabs-list button.timeline-items-tab.selected) {
background-color: white;
box-shadow:
1px 0px 0px inset var(--st-gray-20),
Expand Down
2 changes: 1 addition & 1 deletion src/components/constraints/ConstraintForm.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@
<PageTitle subTitle={pageSubtitle} title={pageTitle} />

<AssociationForm
allMetadata={$constraints}
allMetadata={$constraints || []}
defaultDefinitionCode={`export default (): Constraint => {\n\n}\n`}
displayName="Constraint"
{hasCreateDefinitionCodePermission}
Expand Down
15 changes: 8 additions & 7 deletions src/components/constraints/Constraints.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import { base } from '$app/paths';
import type { ICellRendererParams, ValueGetterParams } from 'ag-grid-community';
import { SearchParameters } from '../../enums/searchParameters';
import { constraints, constraintsColumns } from '../../stores/constraints';
import { constraints, constraintsColumns, initialConstraintsLoading } from '../../stores/constraints';
import type { User } from '../../types/app';
import type { ConstraintMetadata } from '../../types/constraint';
import type { DataGridColumnDef, DataGridRowSelection, RowId } from '../../types/data-grid';
Expand Down Expand Up @@ -82,7 +82,6 @@
resizable: true,
sortable: false,
width: 220,
wrapText: true,
},
];
const permissionError = 'You do not have permission to create a constraint.';
Expand All @@ -94,15 +93,15 @@
let hasPermission: boolean = false;
let selectedConstraint: ConstraintMetadata | null = null;

$: filteredConstraints = $constraints.filter(constraint => {
$: filteredConstraints = ($constraints || []).filter(constraint => {
const filterTextLowerCase = filterText.toLowerCase();
const includesId = `${constraint.id}`.includes(filterTextLowerCase);
const includesName = constraint.name.toLocaleLowerCase().includes(filterTextLowerCase);
return includesId || includesName;
});
$: hasPermission = featurePermissions.constraints.canCreate(user);
$: if (selectedConstraint !== null) {
const found = $constraints.findIndex(constraint => constraint.id === selectedConstraint?.id);
const found = ($constraints || []).findIndex(constraint => constraint.id === selectedConstraint?.id);
if (found === -1) {
selectedConstraint = null;
}
Expand Down Expand Up @@ -166,14 +165,14 @@

function deleteConstraintContext(event: CustomEvent<RowId[]>) {
const id = event.detail[0] as number;
const constraint = $constraints.find(c => c.id === id);
const constraint = ($constraints || []).find(c => c.id === id);
if (constraint) {
deleteConstraint(constraint);
}
}

function editConstraint({ id }: Pick<ConstraintMetadata, 'id'>) {
const constraint = $constraints.find(c => c.id === id);
const constraint = ($constraints || []).find(c => c.id === id);
goto(`${base}/constraints/edit/${id}?${SearchParameters.REVISION}=${constraint?.versions[0].revision}`);
}

Expand Down Expand Up @@ -230,8 +229,10 @@
</svelte:fragment>

<svelte:fragment slot="body">
{#if filteredConstraints.length}
{#if $initialConstraintsLoading || filteredConstraints.length}
<SingleActionDataGrid
showLoadingSkeleton
loading={$initialConstraintsLoading}
{columnDefs}
hasEdit={true}
{hasDeletePermission}
Expand Down
12 changes: 10 additions & 2 deletions src/components/constraints/ConstraintsPanel.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
constraintVisibilityMap,
constraintsMap,
constraintsStatus,
initialConstraintPlanSpecsLoading,
initialConstraintRunsLoading,
initialConstraintsLoading,
setAllConstraintsVisible,
setConstraintVisibility,
} from '../../stores/constraints';
Expand All @@ -42,6 +45,7 @@
import { required } from '../../utilities/validators';
import CollapsibleListControls from '../CollapsibleListControls.svelte';
import DatePickerField from '../form/DatePickerField.svelte';
import Loading from '../Loading.svelte';
import GridMenu from '../menus/GridMenu.svelte';
import DatePickerActionButton from '../ui/DatePicker/DatePickerActionButton.svelte';
import Panel from '../ui/Panel.svelte';
Expand Down Expand Up @@ -113,7 +117,7 @@
$: filteredConstraintResponses = Object.values(constraintToConstraintResponseMap).filter(r =>
filteredConstraints.find(c => c.constraint_id === r.constraintId),
);
$: numOfPrivateConstraints = $constraintPlanSpecs.length - $allowedConstraintSpecs.length;
$: numOfPrivateConstraints = ($constraintPlanSpecs || []).length - $allowedConstraintSpecs.length;

$: totalViolationCount = getViolationCount(Object.values($constraintResponseMap));
$: filteredViolationCount = getViolationCount(Object.values(filteredConstraintResponses));
Expand Down Expand Up @@ -313,7 +317,11 @@
</CollapsibleListControls>

<div class="pt-2">
{#if !filteredConstraints.length}
{#if $initialConstraintsLoading || $initialConstraintPlanSpecsLoading || $initialConstraintRunsLoading}
<div class="p-1">
<Loading />
</div>
{:else if !filteredConstraints.length}
<div class="pt-1 st-typography-label filter-label-row">
<div class="filter-label">No constraints found</div>
<div class="private-label">
Expand Down
1 change: 0 additions & 1 deletion src/components/expansion/ExpansionRules.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@
resizable: true,
sortable: false,
width: 220,
wrapText: true,
},
];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -545,7 +545,7 @@
{#each selectedSourceLinkedDerivationGroupsPlans as linkedPlanDerivationGroup}
<div class="st-typography-body collapse-important-text">
<a href="{base}/plans/{linkedPlanDerivationGroup.plan_id}">
{$plans.find(plan => {
{($plans || []).find(plan => {
return linkedPlanDerivationGroup.plan_id === plan.id;
})?.name}
</a>
Expand Down
2 changes: 2 additions & 0 deletions src/components/menus/PlanMenu.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import ChevronDownIcon from '@nasa-jpl/stellar/icons/chevron_down.svg?component';
import { PlanStatusMessages } from '../../enums/planStatusMessages';
import { planReadOnly } from '../../stores/plan';
import { initialPlanSnapshotsLoading } from '../../stores/planSnapshots';
import { viewTogglePanel } from '../../stores/views';
import type { User } from '../../types/app';
import type { Plan } from '../../types/plan';
Expand Down Expand Up @@ -157,6 +158,7 @@
{/if}
<MenuDivider />
<MenuItem
disabled={$initialPlanSnapshotsLoading}
on:click={createPlanSnapshot}
use={[
[
Expand Down
2 changes: 1 addition & 1 deletion src/components/modals/CreatePlanSnapshotModal.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
}>();

let createButtonDisabled: boolean = true;
let snapshotName: string = `${plan.name} – Snapshot ${$planSnapshots.length + 1}`;
let snapshotName: string = `${plan.name} – Snapshot ${($planSnapshots || []).length + 1}`;
let snapshotDescription: string = '';
let snapshotTags: Tag[] = [];

Expand Down
Loading
Loading