This is an automated email from the ASF dual-hosted git repository.

panyuepeng pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/flink.git

commit 096f031b9502337979c06f067c1289fe03173aaf
Author: och5351 <[email protected]>
AuthorDate: Wed Apr 15 19:35:12 2026 +0900

    [FLINK-38898][runtime-web] Refactor Rescale Details related parts into 
templates for reusing in Rescales/Overview and Rescales/History
    
    Co-authored-by: Yuepeng Pan <[email protected]>
    Co-authored-by: Matthias Pohl <[email protected]>
---
 .../pages/job/rescales/job-rescales.component.html | 515 +++++----------------
 .../pages/job/rescales/job-rescales.component.less |  42 --
 2 files changed, 103 insertions(+), 454 deletions(-)

diff --git 
a/flink-runtime-web/web-dashboard/src/app/pages/job/rescales/job-rescales.component.html
 
b/flink-runtime-web/web-dashboard/src/app/pages/job/rescales/job-rescales.component.html
index 1b4342fac02..5bc5c64f5de 100644
--- 
a/flink-runtime-web/web-dashboard/src/app/pages/job/rescales/job-rescales.component.html
+++ 
b/flink-runtime-web/web-dashboard/src/app/pages/job/rescales/job-rescales.component.html
@@ -24,9 +24,9 @@
   (nzSelectedIndexChange)="refresh()"
 >
   <nz-tab nzTitle="Overview">
-    <!-- Reusable template for rescale details -->
-    <ng-template #rescaleDetailsTemplate let-rescale="rescale">
-      <div class="overview-rescale-section">
+    <!-- Reusable template for rescale details - unified version with 
containerClass parameter -->
+    <ng-template #rescaleDetailsTemplate let-rescale="rescale" 
let-containerClass="containerClass">
+      <div [class]="containerClass || 'rescale-details-box'">
         <h3><strong>Rescale Details</strong></h3>
         <div>
           <span>
@@ -251,185 +251,114 @@
       </div>
     </ng-template>
 
-    <ng-container *ngIf="rescalesOverview">
-      <div class="rescale-header rescale-counts-header">
-        <h3><strong>Rescale Counts</strong></h3>
-        <span class="rescale-time-info">
+    <!-- Reusable template for latest rescale section (like checkpoint 
component) -->
+    <ng-template #latestRescaleTemplate let-title="title" 
let-rescale="rescale">
+      <tr>
+        <td>
+          <strong>{{ title }}</strong>
+        </td>
+        <td *ngIf="rescale">
           <span>
-            <strong>Total:</strong>
-            {{ getTotalRescaleCount() }}
+            <strong>Start Time:</strong>
+            {{ rescale.startTimestampInMillis | date: 'yyyy-MM-dd 
HH:mm:ss.SSS' }}
           </span>
           <nz-divider nzType="vertical"></nz-divider>
           <span>
-            <strong>In Progress:</strong>
-            {{ rescalesOverview.rescalesCounts.inProgress }}
+            <strong>End Time:</strong>
+            {{
+              rescale.endTimestampInMillis
+                ? (rescale.endTimestampInMillis | date: 'yyyy-MM-dd 
HH:mm:ss.SSS')
+                : '-'
+            }}
           </span>
           <nz-divider nzType="vertical"></nz-divider>
           <span>
-            <strong>Completed:</strong>
-            {{ rescalesOverview.rescalesCounts.completed }}
+            <strong>Duration:</strong>
+            {{
+              (rescale.endTimestampInMillis || Date.now()) - 
rescale.startTimestampInMillis
+                | humanizeDuration
+            }}
           </span>
-          <nz-divider nzType="vertical"></nz-divider>
-          <span>
-            <strong>Failed:</strong>
-            {{ rescalesOverview.rescalesCounts.failed }}
-          </span>
-          <nz-divider nzType="vertical"></nz-divider>
-          <span>
-            <strong>Ignored:</strong>
-            {{ rescalesOverview.rescalesCounts.ignored }}
-          </span>
-        </span>
-      </div>
-      <nz-divider></nz-divider>
-
-      <ng-container *ngIf="rescalesOverview.latest.completed">
-        <div class="rescale-header">
-          <h3><strong>Latest Completed Rescale</strong></h3>
-          <span class="rescale-time-info">
-            <span>
-              <strong>Start Time:</strong>
-              {{
-                rescalesOverview.latest.completed.startTimestampInMillis
-                  | date: 'yyyy-MM-dd HH:mm:ss.SSS'
-              }}
-            </span>
-            <nz-divider nzType="vertical"></nz-divider>
-            <span>
-              <strong>End Time:</strong>
-              {{
-                rescalesOverview.latest.completed.endTimestampInMillis
-                  ? (rescalesOverview.latest.completed.endTimestampInMillis
-                    | date: 'yyyy-MM-dd HH:mm:ss.SSS')
-                  : '-'
-              }}
-            </span>
-            <nz-divider nzType="vertical"></nz-divider>
-            <span>
-              <strong>Duration:</strong>
-              {{
-                (rescalesOverview.latest.completed.endTimestampInMillis || 
Date.now()) -
-                  rescalesOverview.latest.completed.startTimestampInMillis | 
humanizeDuration
-              }}
-            </span>
-          </span>
-        </div>
-        <nz-divider></nz-divider>
-        <ng-container
-          *ngTemplateOutlet="
-            rescaleDetailsTemplate;
-            context: { rescale: rescalesOverview.latest.completed }
-          "
-        ></ng-container>
-      </ng-container>
-      <ng-container *ngIf="!rescalesOverview.latest.completed">
-        <div class="rescale-header">
-          <h3><strong>Latest Completed Rescale</strong></h3>
-          <span class="rescale-time-info">None</span>
-        </div>
-        <nz-divider></nz-divider>
-      </ng-container>
-
-      <ng-container *ngIf="rescalesOverview.latest.ignored">
-        <div class="rescale-header">
-          <h3><strong>Latest Ignored Rescale</strong></h3>
-          <span class="rescale-time-info">
-            <span>
-              <strong>Start Time:</strong>
-              {{
-                rescalesOverview.latest.ignored.startTimestampInMillis
-                  | date: 'yyyy-MM-dd HH:mm:ss.SSS'
-              }}
-            </span>
-            <nz-divider nzType="vertical"></nz-divider>
-            <span>
-              <strong>End Time:</strong>
-              {{
-                rescalesOverview.latest.ignored.endTimestampInMillis
-                  ? (rescalesOverview.latest.ignored.endTimestampInMillis
-                    | date: 'yyyy-MM-dd HH:mm:ss.SSS')
-                  : '-'
-              }}
-            </span>
-            <nz-divider nzType="vertical"></nz-divider>
-            <span>
-              <strong>Duration:</strong>
-              {{
-                (rescalesOverview.latest.ignored.endTimestampInMillis || 
Date.now()) -
-                  rescalesOverview.latest.ignored.startTimestampInMillis | 
humanizeDuration
-              }}
-            </span>
-          </span>
-        </div>
-        <nz-divider></nz-divider>
-        <ng-container
-          *ngTemplateOutlet="
-            rescaleDetailsTemplate;
-            context: { rescale: rescalesOverview.latest.ignored }
-          "
-        ></ng-container>
-      </ng-container>
-      <ng-container *ngIf="!rescalesOverview.latest.ignored">
-        <div class="rescale-header">
-          <h3><strong>Latest Ignored Rescale</strong></h3>
-          <span class="rescale-time-info">None</span>
-        </div>
-        <nz-divider></nz-divider>
-      </ng-container>
+        </td>
+        <td *ngIf="!rescale">None</td>
+      </tr>
+      <tr *ngIf="rescale">
+        <td colspan="2" class="collapse-td">
+          <ng-container
+            *ngTemplateOutlet="rescaleDetailsTemplate; context: { rescale: 
rescale }"
+          ></ng-container>
+        </td>
+      </tr>
+    </ng-template>
 
-      <ng-container *ngIf="rescalesOverview.latest.failed">
-        <div class="rescale-header">
-          <h3><strong>Latest Failed Rescale</strong></h3>
-          <span class="rescale-time-info">
-            <span>
-              <strong>Start Time:</strong>
-              {{
-                rescalesOverview.latest.failed.startTimestampInMillis
-                  | date: 'yyyy-MM-dd HH:mm:ss.SSS'
-              }}
-            </span>
-            <nz-divider nzType="vertical"></nz-divider>
-            <span>
-              <strong>End Time:</strong>
-              {{
-                rescalesOverview.latest.failed.endTimestampInMillis
-                  ? (rescalesOverview.latest.failed.endTimestampInMillis
-                    | date: 'yyyy-MM-dd HH:mm:ss.SSS')
-                  : '-'
-              }}
-            </span>
-            <nz-divider nzType="vertical"></nz-divider>
-            <span>
-              <strong>Duration:</strong>
-              {{
-                (rescalesOverview.latest.failed.endTimestampInMillis || 
Date.now()) -
-                  rescalesOverview.latest.failed.startTimestampInMillis | 
humanizeDuration
-              }}
-            </span>
-          </span>
-        </div>
-        <nz-divider></nz-divider>
-        <ng-container
-          *ngTemplateOutlet="
-            rescaleDetailsTemplate;
-            context: { rescale: rescalesOverview.latest.failed }
-          "
-        ></ng-container>
-      </ng-container>
-      <ng-container *ngIf="!rescalesOverview.latest.failed">
-        <div class="rescale-header">
-          <h3><strong>Latest Failed Rescale</strong></h3>
-          <span class="rescale-time-info">None</span>
-        </div>
-        <nz-divider></nz-divider>
-      </ng-container>
-    </ng-container>
+    <nz-table
+      class="no-border small"
+      [nzData]="rescalesOverview ? [''] : []"
+      [nzSize]="'small'"
+      [nzFrontPagination]="false"
+      [nzShowPagination]="false"
+    >
+      <tbody>
+        <ng-container *ngIf="rescalesOverview">
+          <tr>
+            <td><strong>Rescale Counts</strong></td>
+            <td>
+              <span>
+                <strong>Total:</strong>
+                {{ getTotalRescaleCount() }}
+              </span>
+              <nz-divider nzType="vertical"></nz-divider>
+              <span>
+                <strong>In Progress:</strong>
+                {{ rescalesOverview.rescalesCounts.inProgress }}
+              </span>
+              <nz-divider nzType="vertical"></nz-divider>
+              <span>
+                <strong>Completed:</strong>
+                {{ rescalesOverview.rescalesCounts.completed }}
+              </span>
+              <nz-divider nzType="vertical"></nz-divider>
+              <span>
+                <strong>Failed:</strong>
+                {{ rescalesOverview.rescalesCounts.failed }}
+              </span>
+              <nz-divider nzType="vertical"></nz-divider>
+              <span>
+                <strong>Ignored:</strong>
+                {{ rescalesOverview.rescalesCounts.ignored }}
+              </span>
+            </td>
+          </tr>
+          <ng-container
+            *ngTemplateOutlet="
+              latestRescaleTemplate;
+              context: {
+                title: 'Latest Completed Rescale',
+                rescale: rescalesOverview.latest.completed
+              }
+            "
+          ></ng-container>
+          <ng-container
+            *ngTemplateOutlet="
+              latestRescaleTemplate;
+              context: { title: 'Latest Ignored Rescale', rescale: 
rescalesOverview.latest.ignored }
+            "
+          ></ng-container>
+          <ng-container
+            *ngTemplateOutlet="
+              latestRescaleTemplate;
+              context: { title: 'Latest Failed Rescale', rescale: 
rescalesOverview.latest.failed }
+            "
+          ></ng-container>
+        </ng-container>
+      </tbody>
+    </nz-table>
   </nz-tab>
   <nz-tab nzTitle="History">
     <nz-table
       class="no-border small"
       [nzSize]="'small'"
-      [nzData]="jobRescaleDetails || []"
+      [nzData]="rescalesHistory || []"
       [nzFrontPagination]="false"
       [nzShowPagination]="false"
     >
@@ -524,250 +453,12 @@
           <tr [nzExpand]="isExpanded(jobRescaleDetails.rescaleUuid)">
             <td colspan="10" *ngIf="isExpanded(jobRescaleDetails.rescaleUuid)" 
class="collapse-td">
               <div class="rescale-details-wrapper">
-                <div class="rescale-details-box">
-                  <h3><strong>Rescale Details</strong></h3>
-                  <tr>
-                    <td>
-                      <span>
-                        <strong>Rescale UUID:</strong>
-                        {{ truncateUuid(jobRescaleDetails.rescaleUuid) }}
-                      </span>
-                      <nz-divider nzType="vertical"></nz-divider>
-                      <span>
-                        <strong>Requirements ID:</strong>
-                        {{ 
truncateUuid(jobRescaleDetails.resourceRequirementsUuid) }}
-                      </span>
-                      <nz-divider nzType="vertical"></nz-divider>
-                      <span>
-                        <strong>Attempt ID:</strong>
-                        {{ jobRescaleDetails.rescaleAttemptId }}
-                      </span>
-                      <nz-divider nzType="vertical"></nz-divider>
-                      <span>
-                        <strong>Trigger Cause:</strong>
-                        {{ jobRescaleDetails.triggerCause }}
-                      </span>
-                      <nz-divider nzType="vertical"></nz-divider>
-                      <span>
-                        <strong>Terminal State:</strong>
-                        {{ jobRescaleDetails?.terminalState || '-' }}
-                      </span>
-                      <nz-divider nzType="vertical"></nz-divider>
-                      <span>
-                        <strong>Terminal Reason:</strong>
-                        {{ jobRescaleDetails?.terminatedReason || '-' }}
-                      </span>
-                    </td>
-                  </tr>
-                  <ng-container 
*ngIf="getDetail(jobRescaleDetails.rescaleUuid) as detail">
-                    <nz-table
-                      class="small"
-                      [nzData]="detail.vertices | keyvalue"
-                      [nzSize]="'small'"
-                      [nzFrontPagination]="false"
-                      [nzShowPagination]="false"
-                      [nzTitle]="verticesTitle"
-                      [nzBordered]="true"
-                    >
-                      <thead>
-                        <tr>
-                          <th
-                            nz-tooltip
-                            nzTooltipTitle="The unique ID of target JobVertex 
consists of 32 hexadecimal characters"
-                          >
-                            <strong>ID</strong>
-                          </th>
-                          <th nz-tooltip nzTooltipTitle="The short name of 
target vertex">
-                            <strong>Name</strong>
-                          </th>
-                          <th
-                            nz-tooltip
-                            nzTooltipTitle="The previous parallelism of target 
vertex before the current rescale"
-                          >
-                            <strong>Previous Parallelism</strong>
-                          </th>
-                          <th
-                            nz-tooltip
-                            nzTooltipTitle="The acquired parallelism of target 
vertex after the current rescale"
-                          >
-                            <strong>Acquired Parallelism</strong>
-                          </th>
-                          <th
-                            nz-tooltip
-                            nzTooltipTitle="The desired parallelism of the 
target vertex"
-                          >
-                            <strong>Desired Parallelism</strong>
-                          </th>
-                          <th
-                            nz-tooltip
-                            nzTooltipTitle="The minimal parallelism of target 
vertex to run"
-                          >
-                            <strong>Sufficient Parallelism</strong>
-                          </th>
-                          <th
-                            nz-tooltip
-                            nzTooltipTitle="The unique ID of the slot sharing 
group consists of 32 hexadecimal characters"
-                          >
-                            <strong>Slot Sharing Group ID</strong>
-                          </th>
-                        </tr>
-                      </thead>
-                      <tbody>
-                        <tr *ngFor="let vertex of detail.vertices | keyvalue">
-                          <td nz-tooltip 
[nzTooltipTitle]="vertex.value.jobVertexId">
-                            {{ truncateUuid(vertex.value.jobVertexId) }}
-                          </td>
-                          <td nz-tooltip 
[nzTooltipTitle]="vertex.value.jobVertexName">
-                            {{ truncateName(vertex.value.jobVertexName) }}
-                          </td>
-                          <td>{{ vertex.value.preRescaleParallelism }}</td>
-                          <td>{{ vertex.value.postRescaleParallelism || '-' 
}}</td>
-                          <td>{{ vertex.value.desiredParallelism }}</td>
-                          <td>{{ vertex.value.sufficientParallelism }}</td>
-                          <td nz-tooltip 
[nzTooltipTitle]="vertex.value.slotSharingGroupId">
-                            {{ truncateUuid(vertex.value.slotSharingGroupId) }}
-                          </td>
-                        </tr>
-                      </tbody>
-                    </nz-table>
-
-                    <nz-table
-                      class="small"
-                      [nzData]="detail.slots | keyvalue"
-                      [nzSize]="'small'"
-                      [nzFrontPagination]="false"
-                      [nzShowPagination]="false"
-                      [nzTitle]="slotsTitle"
-                      [nzBordered]="true"
-                    >
-                      <thead>
-                        <tr>
-                          <th
-                            nz-tooltip
-                            nzTooltipTitle="The ID of the slot sharing group 
to which the slot belongs consists of 32 hexadecimal characters"
-                          >
-                            <strong>Slot Sharing Group ID</strong>
-                          </th>
-                          <th
-                            nz-tooltip
-                            nzTooltipTitle="The name of the slot sharing group 
to which the slot belongs"
-                          >
-                            <strong>Slot Sharing Group Name</strong>
-                          </th>
-                          <th
-                            nz-tooltip
-                            nzTooltipTitle="The previous number of slots 
before the rescale"
-                          >
-                            <strong>Previous Slots</strong>
-                          </th>
-                          <th
-                            nz-tooltip
-                            nzTooltipTitle="The acquired number of slots after 
the rescale"
-                          >
-                            <strong>Acquired Slots</strong>
-                          </th>
-                          <th
-                            nz-tooltip
-                            nzTooltipTitle="The desired number of slots of the 
rescale"
-                          >
-                            <strong>Desired Slots</strong>
-                          </th>
-                          <th
-                            nz-tooltip
-                            nzTooltipTitle="The minimal number of slots to 
deploy tasks in the rescale"
-                          >
-                            <strong>Sufficient Slots</strong>
-                          </th>
-                          <th
-                            nz-tooltip
-                            nzTooltipTitle="The required resource profile of 
the slot sharing group in the rescale"
-                          >
-                            <strong>Required Profile</strong>
-                          </th>
-                          <th
-                            nz-tooltip
-                            nzTooltipTitle="The acquired resource profile of 
the slot sharing group in the rescale"
-                          >
-                            <strong>Acquired Profile</strong>
-                          </th>
-                        </tr>
-                      </thead>
-                      <tbody>
-                        <tr *ngFor="let slot of detail.slots | keyvalue">
-                          <td nz-tooltip 
[nzTooltipTitle]="slot.value.slotSharingGroupId">
-                            {{ truncateUuid(slot.value.slotSharingGroupId) }}
-                          </td>
-                          <td>{{ slot.value.slotSharingGroupName }}</td>
-                          <td>{{ slot.value.preRescaleSlots }}</td>
-                          <td>{{ slot.value.postRescaleSlots || '-' }}</td>
-                          <td>{{ slot.value.desiredSlots }}</td>
-                          <td>{{ slot.value.minimalRequiredSlots }}</td>
-                          <td>
-                            <pre style="margin: 0">{{
-                              slot.value.requestResourceProfile | json
-                            }}</pre>
-                          </td>
-                          <td>
-                            <pre style="margin: 0">{{
-                              slot.value.acquiredResourceProfile | json
-                            }}</pre>
-                          </td>
-                        </tr>
-                      </tbody>
-                    </nz-table>
-
-                    <nz-table
-                      class="small"
-                      [nzData]="detail.schedulerStates"
-                      [nzSize]="'small'"
-                      [nzFrontPagination]="false"
-                      [nzShowPagination]="false"
-                      [nzTitle]="schedulerStatesTitle"
-                      [nzBordered]="true"
-                    >
-                      <thead>
-                        <tr>
-                          <th nz-tooltip nzTooltipTitle="The scheduler state 
name">
-                            <strong>State</strong>
-                          </th>
-                          <th nz-tooltip nzTooltipTitle="The time to enter the 
state">
-                            <strong>Enter Time</strong>
-                          </th>
-                          <th nz-tooltip nzTooltipTitle="The time to leave the 
state">
-                            <strong>Leave Time</strong>
-                          </th>
-                          <th
-                            nz-tooltip
-                            nzTooltipTitle="The duration time from enter time 
to leave time of the state"
-                          >
-                            <strong>Duration</strong>
-                          </th>
-                          <th
-                            nz-tooltip
-                            nzTooltipTitle="The exception information about 
current rescale during the state"
-                          >
-                            <strong>Exception</strong>
-                          </th>
-                        </tr>
-                      </thead>
-                      <tbody>
-                        <tr *ngFor="let state of detail.schedulerStates">
-                          <td>{{ state.state }}</td>
-                          <td>
-                            {{ state.enterTimestampInMillis | date: 
'yyyy-MM-dd HH:mm:ss.SSS' }}
-                          </td>
-                          <td>
-                            {{ state.leaveTimestampInMillis | date: 
'yyyy-MM-dd HH:mm:ss.SSS' }}
-                          </td>
-                          <td>{{ state.durationInMillis | humanizeDuration 
}}</td>
-                          <td>{{ state.stringifiedException }}</td>
-                        </tr>
-                      </tbody>
-                    </nz-table>
-                  </ng-container>
-
-                  <div 
*ngIf="!getDetail(jobRescaleDetails.rescaleUuid)">Loading...</div>
-                </div>
+                <ng-container
+                  *ngTemplateOutlet="
+                    rescaleDetailsTemplate;
+                    context: { rescale: jobRescaleDetails, containerClass: 
'rescale-details-box' }
+                  "
+                ></ng-container>
               </div>
             </td>
           </tr>
diff --git 
a/flink-runtime-web/web-dashboard/src/app/pages/job/rescales/job-rescales.component.less
 
b/flink-runtime-web/web-dashboard/src/app/pages/job/rescales/job-rescales.component.less
index a5ad73dde77..aa43d203d71 100644
--- 
a/flink-runtime-web/web-dashboard/src/app/pages/job/rescales/job-rescales.component.less
+++ 
b/flink-runtime-web/web-dashboard/src/app/pages/job/rescales/job-rescales.component.less
@@ -31,28 +31,6 @@
       > nz-divider {
         margin: 8px 0;
       }
-
-      .rescale-header {
-        display: flex;
-        align-items: center;
-        margin-top: 8px;
-        margin-bottom: 8px;
-
-        h3 {
-          flex-shrink: 0;
-          width: 280px;
-          margin: 0;
-        }
-
-        .rescale-time-info {
-          color: rgba(0, 0, 0, 0.85);
-          font-size: 14px;
-        }
-
-        &.rescale-counts-header {
-          margin-top: -2px;
-        }
-      }
     }
 
     .ant-tabs-nav-list {
@@ -95,26 +73,6 @@ nz-empty {
   padding: 24px;
 }
 
-.overview-rescale-section {
-  margin: 16px 0;
-  padding: 16px;
-  border: 1px solid #f0f0f0;
-  background-color: #fff;
-
-  h3 {
-    margin-top: 0;
-    margin-bottom: 8px;
-  }
-
-  nz-table {
-    margin-bottom: 16px;
-
-    &:last-child {
-      margin-bottom: 0;
-    }
-  }
-}
-
 .rescale-details-wrapper {
   display: block;
   box-sizing: border-box;

Reply via email to