bobbai00 commented on code in PR #3772:
URL: https://github.com/apache/texera/pull/3772#discussion_r2418143060


##########
core/gui/src/app/workspace/service/workflow-result-export/workflow-result-export.service.ts:
##########
@@ -60,34 +78,126 @@ export class WorkflowResultExportService {
       
this.workflowActionService.getJointGraphWrapper().getJointOperatorHighlightStream(),
       
this.workflowActionService.getJointGraphWrapper().getJointOperatorUnhighlightStream()
     ).subscribe(() => {
-      // check if there are any results to export on highlighted operators 
(either paginated or snapshot)
-      this.hasResultToExportOnHighlightedOperators =
-        
isNotInExecution(this.executeWorkflowService.getExecutionState().state) &&
-        this.workflowActionService
-          .getJointGraphWrapper()
-          .getCurrentHighlightedOperatorIDs()
-          .filter(
-            operatorId =>
-              this.workflowResultService.hasAnyResult(operatorId) ||
-              
this.workflowResultService.getResultService(operatorId)?.getCurrentResultSnapshot()
 !== undefined
-          ).length > 0;
-
-      // check if there are any results to export on all operators (either 
paginated or snapshot)
-      let staticHasResultToExportOnAllOperators =
-        
isNotInExecution(this.executeWorkflowService.getExecutionState().state) &&
-        this.workflowActionService
-          .getTexeraGraph()
-          .getAllOperators()
-          .map(operator => operator.operatorID)
-          .filter(
-            operatorId =>
-              this.workflowResultService.hasAnyResult(operatorId) ||
-              
this.workflowResultService.getResultService(operatorId)?.getCurrentResultSnapshot()
 !== undefined
-          ).length > 0;
-
-      // Notify subscribers of changes
-      
this.hasResultToExportOnAllOperators.next(staticHasResultToExportOnAllOperators);
+      this.updateExportAvailabilityFlags();
+    });
+  }
+
+  /**
+   * Computes restriction analysis by calling the backend API.
+   *
+   * The backend analyzes the workflow to identify operators that are 
restricted from export
+   * due to non-downloadable dataset dependencies. The restriction propagates 
through the
+   * workflow graph via data flow.
+   *
+   * @returns Observable that emits the restriction analysis result
+   */
+  public computeRestrictionAnalysis(): 
Observable<WorkflowResultDownloadability> {
+    const workflowId = this.workflowActionService.getWorkflow().wid;
+    if (!workflowId) {
+      return of({ restrictedOperatorMap: new Map<string, Set<string>>() });
+    }
+
+    return 
this.downloadService.getWorkflowResultDownloadability(workflowId).pipe(
+      map(backendResponse => {
+        // Convert backend format to Map<operatorId, Set<datasetLabel>>
+        const restrictedOperatorMap = new Map<string, Set<string>>();
+        Object.entries(backendResponse).forEach(([operatorId, datasetLabels]) 
=> {
+          restrictedOperatorMap.set(operatorId, new Set(datasetLabels));
+        });
+        return { restrictedOperatorMap };
+      }),
+      catchError(() => {
+        return of({
+          restrictedOperatorMap: new Map<string, Set<string>>(),
+        });
+      })
+    );
+  }
+
+  /**
+   * Updates UI flags that control export button visibility and availability.
+   *
+   * Checks execution state and result availability to determine:
+   * - hasResultToExportOnHighlightedOperators: for context menu export button
+   * - hasResultToExportOnAllOperators: for top menu export button
+   *
+   * Export is only available when execution is idle and operators have 
results.
+   */
+  private updateExportAvailabilityFlags(): void {
+    const executionIdle = 
isNotInExecution(this.executeWorkflowService.getExecutionState().state);
+
+    const highlightedOperators = 
this.workflowActionService.getJointGraphWrapper().getCurrentHighlightedOperatorIDs();
+
+    const highlightedHasResult = highlightedOperators.some(
+      operatorId =>
+        this.workflowResultService.hasAnyResult(operatorId) ||
+        
this.workflowResultService.getResultService(operatorId)?.getCurrentResultSnapshot()
 !== undefined
+    );
+
+    this.hasResultToExportOnHighlightedOperators = executionIdle && 
highlightedHasResult;
+
+    const allOperatorIds = this.workflowActionService
+      .getTexeraGraph()
+      .getAllOperators()
+      .map(operator => operator.operatorID);
+
+    const hasAnyResult =
+      executionIdle &&
+      allOperatorIds.some(
+        operatorId =>
+          this.workflowResultService.hasAnyResult(operatorId) ||
+          
this.workflowResultService.getResultService(operatorId)?.getCurrentResultSnapshot()
 !== undefined
+      );
+
+    this.hasResultToExportOnAllOperators.next(hasAnyResult);
+  }
+
+  /**
+   * Filters operator IDs to return only those that are not restricted by 
dataset access controls.
+   *
+   * @param operatorIds Array of operator IDs to filter
+   * @param restrictedOperatorMap Map of restricted operators to blocking 
dataset labels
+   * @returns Array of operator IDs that can be exported
+   */
+  public getExportableOperatorIds(

Review Comment:
   Below functions are purely statically computing operator Ids using the all 
operator Ids and the restrictedOperatorMap.
   
   Can you move all of them to the `WorkflowResultDownloadability` as its 
member functions?



##########
core/gui/src/app/workspace/component/result-exportation/result-exportation.component.ts:
##########
@@ -98,6 +114,21 @@ export class ResultExportationComponent implements OnInit {
       operatorIds = 
this.workflowActionService.getJointGraphWrapper().getCurrentHighlightedOperatorIDs();
     }
 
+    this.exportableOperatorIds = 
this.workflowResultExportService.getExportableOperatorIds(

Review Comment:
   these can be removed after you make the above changes



##########
core/gui/src/app/workspace/component/result-exportation/result-exportation.component.ts:
##########
@@ -52,6 +55,12 @@ export class ResultExportationComponent implements OnInit {
   containsBinaryData: boolean = false;
   inputDatasetName = "";
   selectedComputingUnit: DashboardWorkflowComputingUnit | null = null;
+  exportableOperatorIds: string[] = [];

Review Comment:
   As exportableOperatorIds and several below variables can be computed from 
`restrictedOperatorMap` using a function, please remove them and only keep 
`restrictedOperatorMap`. Also the type of `restrictedOperatorMap` should be 
`WorkflowResultDownloadability`, not Map, right?



##########
core/gui/src/app/workspace/service/workflow-result-export/workflow-result-export.service.ts:
##########
@@ -26,14 +26,32 @@ import { PaginatedResultEvent, ResultExportResponse } from 
"../../types/workflow
 import { NotificationService } from 
"../../../common/service/notification/notification.service";
 import { ExecuteWorkflowService } from 
"../execute-workflow/execute-workflow.service";
 import { ExecutionState, isNotInExecution } from 
"../../types/execute-workflow.interface";
-import { filter } from "rxjs/operators";
+import { catchError, filter, map, take, tap } from "rxjs/operators";
 import { OperatorResultService, WorkflowResultService } from 
"../workflow-result/workflow-result.service";
 import { DownloadService } from 
"../../../dashboard/service/user/download/download.service";
 import { HttpResponse } from "@angular/common/http";
 import { ExportWorkflowJsonResponse } from 
"../../../dashboard/service/user/download/download.service";
 import { DashboardWorkflowComputingUnit } from 
"../../types/workflow-computing-unit";
 import { GuiConfigService } from "../../../common/service/gui-config.service";
 
+/**
+ * Result of workflow result downloadability analysis.
+ * Contains information about which operators are restricted from exporting
+ * due to non-downloadable dataset dependencies.
+ */
+export interface WorkflowResultDownloadability {

Review Comment:
   I saw another same definition of `WorkflowResultDownloadability` before this 
one. Keep one 



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to