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

yasithdev pushed a commit to branch feat/generic-experiment-launcher
in repository https://gitbox.apache.org/repos/asf/airavata-portals.git

commit 9d90b2d58f8c03575e21076cd30080575a0cfeae
Author: yasithdev <[email protected]>
AuthorDate: Fri Apr 24 23:26:06 2026 -0400

    refactor(launcher): delete old experiment-editor surface
    
    Remove CreateExperimentContainer, EditExperimentContainer, ExperimentEditor,
    ComputationalResourceSchedulingEditor, QueueSettingsEditor, 
GroupResourceProfileSelector,
    entry-create-experiment.js, and entry-edit-experiment.js. Drop the matching 
view
    functions (create_experiment, edit_experiment, applications, 
get_custom_template) and
    orphaned imports from workspace/views.py. Replace the still-routed 
edit_experiment URL
    with a 301 redirect to /workspace/launch (missed by Task 5). Drop 
create-experiment and
    edit-experiment entries from vite.config.js.
---
 .../ComputationalResourceSchedulingEditor.vue      | 296 -----------
 .../js/components/experiment/ExperimentEditor.vue  | 423 ----------------
 .../experiment/GroupResourceProfileSelector.vue    | 114 -----
 .../components/experiment/QueueSettingsEditor.vue  | 544 ---------------------
 .../js/containers/CreateExperimentContainer.vue    |  99 ----
 .../js/containers/EditExperimentContainer.vue      |  78 ---
 .../js/entry-create-experiment.js                  |  32 --
 .../js/entry-edit-experiment.js                    |  25 -
 .../django_airavata/apps/workspace/urls.py         |   4 +-
 .../django_airavata/apps/workspace/views.py        | 120 -----
 .../django_airavata/apps/workspace/vite.config.js  |   2 -
 11 files changed, 2 insertions(+), 1735 deletions(-)

diff --git 
a/airavata-django-portal/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/experiment/ComputationalResourceSchedulingEditor.vue
 
b/airavata-django-portal/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/experiment/ComputationalResourceSchedulingEditor.vue
deleted file mode 100644
index 6e7c50454..000000000
--- 
a/airavata-django-portal/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/experiment/ComputationalResourceSchedulingEditor.vue
+++ /dev/null
@@ -1,296 +0,0 @@
-<template>
-  <div>
-    <div class="row">
-      <div class="col">
-        <form-group
-          label="Compute Resource"
-          label-for="compute-resource"
-          :feedback="getValidationFeedback('resource_host_id')"
-          :state="getValidationState('resource_host_id')"
-        >
-          <select
-            id="compute-resource"
-            v-model="resource_host_id"
-            class="form-select"
-            required
-            :state="getValidationState('resource_host_id')"
-            :disabled="!computeResourceOptions || 
computeResourceOptions.length === 0"
-            @change="computeResourceChanged(($event.target as 
HTMLSelectElement).value)"
-          >
-            <option :value="null" disabled>Select a Compute Resource</option>
-            <option v-for="opt in computeResourceOptions" :key="opt.value" 
:value="opt.value">
-              {{ opt.text }}
-            </option>
-          </select>
-        </form-group>
-      </div>
-    </div>
-    <div class="row">
-      <div class="col">
-        <QueueSettingsEditor
-          v-if="appDeploymentId"
-          v-model="data"
-          :app-module-id="appModuleId"
-          :app-deployment-id="appDeploymentId"
-          :compute-resource-policy="selectedComputeResourcePolicy"
-          :batch-queue-resource-policies="batchQueueResourcePolicies"
-          @input="queueSettingsChanged"
-          @valid="queueSettingsValidityChanged(true)"
-          @invalid="queueSettingsValidityChanged(false)"
-        >
-        </QueueSettingsEditor>
-      </div>
-    </div>
-  </div>
-</template>
-
-<script setup lang="ts">
-import { ref, computed, watch, onMounted } from "vue";
-import QueueSettingsEditor from "./QueueSettingsEditor.vue";
-import { errors, models, services, utils as apiUtils } from 
"django-airavata-api";
-import { utils } from "django-airavata-common-ui";
-
-type ComputationalResourceSchedulingModel = InstanceType<typeof 
models.ComputationalResourceSchedulingModel>;
-
-interface ComputeResourceOption {
-  value: string;
-  text: string;
-}
-
-interface WorkspacePreferences {
-  most_recent_compute_resource_id?: string | null;
-}
-
-interface GroupResourceProfileData {
-  group_resource_profile_id: string;
-  compute_resource_policies: Array<{ compute_resource_id: string; [key: 
string]: unknown }>;
-  batch_queue_resource_policies: Array<{ compute_resource_id: string; [key: 
string]: unknown }>;
-}
-
-interface ApplicationDeployment {
-  compute_host_id: string;
-  app_deployment_id: string;
-}
-
-const props = defineProps<{
-  modelValue: ComputationalResourceSchedulingModel;
-  appModuleId: string;
-  groupResourceProfileId: string;
-}>();
-
-const emit = defineEmits<{
-  "update:modelValue": [value: ComputationalResourceSchedulingModel];
-  input: [value: ComputationalResourceSchedulingModel];
-  valid: [];
-  invalid: [];
-}>();
-
-// VModelMixin inline
-function copyValue(value: ComputationalResourceSchedulingModel) {
-  return value instanceof models.BaseModel
-    ? (value as unknown as { clone: () => ComputationalResourceSchedulingModel 
}).clone()
-    : value;
-}
-
-const data = 
ref<ComputationalResourceSchedulingModel>(copyValue(props.modelValue));
-
-watch(
-  () => props.modelValue,
-  (newValue) => {
-    data.value = copyValue(newValue);
-  },
-  { deep: true },
-);
-
-watch(
-  data,
-  (newValue, oldValue) => {
-    if (typeof props.modelValue === "object" && newValue === oldValue) {
-      emit("update:modelValue", newValue);
-      emit("input", newValue);
-    } else if (
-      (props.modelValue === null || typeof props.modelValue !== "object") &&
-      newValue !== oldValue
-    ) {
-      emit("update:modelValue", newValue);
-      emit("input", newValue);
-    }
-  },
-  { deep: true },
-);
-
-const computeResources = ref<Record<string, string>>({});
-const applicationDeployments = ref<ApplicationDeployment[]>([]);
-const selectedGroupResourceProfileData = ref<GroupResourceProfileData | 
null>(null);
-const resource_host_id = ref<string | null>(props.modelValue.resource_host_id 
?? null);
-const invalidQueueSettings = ref(false);
-const workspacePreferences = ref<WorkspacePreferences | null>(null);
-
-const localComputationalResourceScheduling = computed(() => data.value);
-
-const computeResourceOptions = computed<ComputeResourceOption[]>(() => {
-  const options = applicationDeployments.value.map((dep) => ({
-    value: dep.compute_host_id,
-    text: dep.compute_host_id in computeResources.value ? 
computeResources.value[dep.compute_host_id] : "",
-  }));
-  options.sort((a, b) => a.text.localeCompare(b.text));
-  return options;
-});
-
-const selectedComputeResourcePolicy = computed(() => {
-  if (selectedGroupResourceProfileData.value === null) return null;
-  return selectedGroupResourceProfileData.value.compute_resource_policies.find(
-    (crp) => crp.compute_resource_id === 
localComputationalResourceScheduling.value.resource_host_id,
-  ) ?? null;
-});
-
-interface BatchQueueResourcePolicyLike {
-  compute_resource_id: string;
-  queuename: string;
-  maxAllowedCores: number;
-  maxAllowedNodes: number;
-  maxAllowedWalltime: number;
-  resourcePolicyId?: string;
-  [key: string]: unknown;
-}
-
-const batchQueueResourcePolicies = computed<BatchQueueResourcePolicyLike[] | 
null>(() => {
-  if (selectedGroupResourceProfileData.value === null) return null;
-  return 
selectedGroupResourceProfileData.value.batch_queue_resource_policies.filter(
-    (bqrp) => bqrp.compute_resource_id === 
localComputationalResourceScheduling.value.resource_host_id,
-  ) as BatchQueueResourcePolicyLike[];
-});
-
-const appDeploymentId = computed<string | null>(() => {
-  if (!resource_host_id.value || applicationDeployments.value.length === 0) 
return null;
-  const selectedDep = applicationDeployments.value.find(
-    (dep) => dep.compute_host_id === resource_host_id.value,
-  );
-  if (!selectedDep) {
-    throw new Error("Failed to find application deployment!");
-  }
-  return selectedDep.app_deployment_id;
-});
-
-const validation = computed(() => {
-  const queueInfo = {};
-  return localComputationalResourceScheduling.value.validate(queueInfo);
-});
-
-const valid = computed(() => !invalidQueueSettings.value && 
Object.keys(validation.value).length === 0);
-
-watch(computeResourceOptions, (newOptions) => {
-  if (resource_host_id.value !== null && !newOptions.find((opt) => opt.value 
=== resource_host_id.value)) {
-    resource_host_id.value = null;
-  }
-  if (
-    resource_host_id.value === null &&
-    workspacePreferences.value?.most_recent_compute_resource_id &&
-    newOptions.find((opt) => opt.value === 
workspacePreferences.value!.most_recent_compute_resource_id)
-  ) {
-    resource_host_id.value = 
workspacePreferences.value.most_recent_compute_resource_id;
-  }
-  if (resource_host_id.value === null && newOptions.length > 0) {
-    resource_host_id.value = newOptions[0].value;
-  }
-  computeResourceChanged(resource_host_id.value);
-});
-
-watch(
-  () => props.groupResourceProfileId,
-  (newGroupResourceProfileId) => {
-    loadApplicationDeployments(props.appModuleId, newGroupResourceProfileId);
-    if (
-      selectedGroupResourceProfileData.value &&
-      selectedGroupResourceProfileData.value.group_resource_profile_id !== 
newGroupResourceProfileId
-    ) {
-      loadGroupResourceProfile();
-    }
-  },
-);
-
-onMounted(() => {
-  loadWorkspacePreferences().then(() => {
-    loadApplicationDeployments(props.appModuleId, 
props.groupResourceProfileId);
-  });
-  loadComputeResourceNames();
-  loadGroupResourceProfile();
-  validate();
-});
-
-function computeResourceChanged(selectedComputeResourceId: string | null) {
-  data.value.resource_host_id = selectedComputeResourceId;
-}
-
-function loadApplicationDeployments(appModuleId: string, 
groupResourceProfileId: string) {
-  services.ApplicationDeploymentService.list(
-    { app_module_id: appModuleId, group_resource_profile_id: 
groupResourceProfileId },
-    { ignoreErrors: true },
-  )
-    .then((deps: unknown) => {
-      applicationDeployments.value = deps as ApplicationDeployment[];
-    })
-    .catch((error: unknown) => {
-      if (!errors.ErrorUtils.isUnauthorizedError(error)) {
-        return Promise.reject(error);
-      }
-    })
-    .catch(apiUtils.FetchUtils.reportError);
-}
-
-function loadGroupResourceProfile() {
-  services.ProjectResourceProfileService.retrieve(
-    { lookup: props.groupResourceProfileId },
-    { ignoreErrors: true },
-  )
-    .then((grp: unknown) => {
-      selectedGroupResourceProfileData.value = grp as GroupResourceProfileData;
-    })
-    .catch((error: unknown) => {
-      if (!errors.ErrorUtils.isUnauthorizedError(error)) {
-        return Promise.reject(error);
-      }
-    })
-    .catch(apiUtils.FetchUtils.reportError);
-}
-
-function loadComputeResourceNames() {
-  services.ComputeResourceService.names().then(
-    (names: unknown) => (computeResources.value = names as Record<string, 
string>),
-  );
-}
-
-function loadWorkspacePreferences(): Promise<void> {
-  return services.WorkspacePreferencesService.get().then(
-    (prefs: unknown) => (workspacePreferences.value = prefs as 
WorkspacePreferences),
-  );
-}
-
-function queueSettingsChanged() {
-  localComputationalResourceScheduling.value.resource_host_id = 
resource_host_id.value;
-  emit("input", data.value);
-}
-
-function queueSettingsValidityChanged(validValue: boolean) {
-  invalidQueueSettings.value = !validValue;
-  validate();
-}
-
-function validate() {
-  if (!valid.value) {
-    emit("invalid");
-  } else {
-    emit("valid");
-  }
-}
-
-function getValidationFeedback(properties: string): unknown {
-  return utils.getProperty(validation.value, properties);
-}
-
-function getValidationState(properties: string): boolean | null {
-  return getValidationFeedback(properties) ? false : null;
-}
-</script>
-
-<style></style>
diff --git 
a/airavata-django-portal/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/experiment/ExperimentEditor.vue
 
b/airavata-django-portal/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/experiment/ExperimentEditor.vue
deleted file mode 100644
index be28bbc44..000000000
--- 
a/airavata-django-portal/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/experiment/ExperimentEditor.vue
+++ /dev/null
@@ -1,423 +0,0 @@
-<template>
-  <div>
-    <UnsavedChangesGuard :dirty="dirty" />
-    <div class="row">
-      <div class="col-auto me-auto">
-        <h1 class="h4 mb-4">
-          <div v-if="appModule" class="application-name text-muted 
text-uppercase">
-            <i class="fa fa-code" aria-hidden="true"></i>
-            {{ appModule.app_module_name }}
-          </div>
-          <slot name="title">Experiment Editor</slot>
-        </h1>
-      </div>
-      <div class="col-auto">
-        <ShareButton
-          ref="shareButton"
-          :entity-id="localExperiment.experiment_id"
-          :entity-label="'Experiment'"
-          :parent-entity-id="localExperiment.project_id"
-          :parent-entity-label="'Project'"
-          :auto-add-default-gateway-users-group="false"
-        />
-      </div>
-    </div>
-    <form novalidate>
-      <div class="row">
-        <div class="col">
-          <form-group
-            label="Experiment Name"
-            label-for="experiment-name"
-            :feedback="getValidationFeedback('experiment_name')"
-            :state="getValidationState('experiment_name')"
-          >
-            <input
-              id="experiment-name"
-              v-model="localExperiment.experiment_name"
-              class="form-control"
-              type="text"
-              required
-              placeholder="Experiment name"
-              :state="getValidationState('experiment_name')"
-            />
-          </form-group>
-          <ExperimentDescriptionEditor v-model="localExperiment.description" />
-        </div>
-      </div>
-      <div class="row">
-        <div class="col">
-          <form-group
-            label="Project"
-            label-for="project"
-            :feedback="getValidationFeedback('project_id')"
-            :state="getValidationState('project_id')"
-          >
-            <select
-              id="project"
-              v-model="localExperiment.project_id"
-              class="form-select"
-              required
-              :state="getValidationState('project_id')"
-            >
-              <option :value="null" disabled>Select a Project</option>
-              <optgroup label="My Projects">
-                <option
-                  v-for="project in myProjectOptions"
-                  :key="project.value"
-                  :value="project.value"
-                >
-                  {{ project.text }}
-                </option>
-              </optgroup>
-              <optgroup label="Projects Shared With Me">
-                <option
-                  v-for="project in sharedProjectOptions"
-                  :key="project.value"
-                  :value="project.value"
-                >
-                  {{ project.text }}
-                </option>
-              </optgroup>
-            </select>
-          </form-group>
-        </div>
-      </div>
-      <div class="row">
-        <div class="col">
-          <WorkspaceNoticesManagementContainer
-            v-if="appInterface && (appInterface as Record<string, 
unknown>).application_description"
-            class="mt-2"
-            :data="[{ notificationMessage: (appInterface as Record<string, 
unknown>).application_description as string | undefined }]"
-          />
-        </div>
-      </div>
-      <div class="row">
-        <div class="col">
-          <h1 class="h4 mt-2 mb-4">Application Configuration</h1>
-        </div>
-      </div>
-      <div class="row">
-        <div class="col">
-          <div class="card border-default">
-            <div class="card-body">
-              <h2 class="h6 mb-3">Application Inputs</h2>
-              <transition-group name="fade">
-                <InputEditorContainer
-                  v-for="experimentInput in localExperiment.experiment_inputs"
-                  v-show="experimentInput.show"
-                  :key="experimentInput.name"
-                  v-model="experimentInput.value"
-                  :experiment-input="experimentInput"
-                  :experiment="localExperiment"
-                  
@invalid="recordInvalidInputEditorValue(experimentInput.name)"
-                  @valid="recordValidInputEditorValue(experimentInput.name)"
-                  @input="inputValueChanged"
-                  @uploadstart="uploadStart(experimentInput.name)"
-                  @uploadend="uploadEnd(experimentInput.name)"
-                />
-              </transition-group>
-            </div>
-          </div>
-        </div>
-      </div>
-      <GroupResourceProfileSelector
-        
v-model="localExperiment.user_configuration_data.group_resource_profile_id"
-        @invalid="invalidGroupResourceProfileSelector = true"
-        @valid="invalidGroupResourceProfileSelector = false"
-      >
-      </GroupResourceProfileSelector>
-      <div class="row">
-        <div class="col">
-          <ComputationalResourceSchedulingEditor
-            
v-if="localExperiment.user_configuration_data.group_resource_profile_id"
-            
v-model="localExperiment.user_configuration_data.computational_resource_scheduling"
-            :app-module-id="appModule.app_module_id"
-            :group-resource-profile-id="
-              localExperiment.user_configuration_data.group_resource_profile_id
-            "
-            @invalid="invalidComputationalResourceSchedulingEditor = true"
-            @valid="invalidComputationalResourceSchedulingEditor = false"
-          >
-          </ComputationalResourceSchedulingEditor>
-        </div>
-      </div>
-      <div class="row">
-        <div class="col">
-          <div class="mb-3" label="Email Settings">
-            <div class="form-check">
-              <input
-                v-model="localExperiment.enable_email_notification"
-                class="form-check-input"
-                type="checkbox"
-              />
-              Receive email notification of experiment status
-            </div>
-          </div>
-        </div>
-      </div>
-      <div class="row">
-        <div id="col-exp-buttons" class="col">
-          <button
-            class="btn btn-success btn-sm"
-            :disabled="isSaveDisabled"
-            @click="saveAndLaunchExperiment"
-          >
-            Save and Launch
-          </button>
-          <button class="btn btn-primary btn-sm" :disabled="isSaveDisabled" 
@click="saveExperiment">
-            Save
-          </button>
-        </div>
-      </div>
-    </form>
-  </div>
-</template>
-
-<script setup lang="ts">
-import { ref, computed, watch, onMounted } from "vue";
-import ComputationalResourceSchedulingEditor from 
"./ComputationalResourceSchedulingEditor.vue";
-import ExperimentDescriptionEditor from "./ExperimentDescriptionEditor.vue";
-import GroupResourceProfileSelector from "./GroupResourceProfileSelector.vue";
-import InputEditorContainer from "./input-editors/InputEditorContainer.vue";
-import { models, services } from "django-airavata-api";
-import { components, utils } from "django-airavata-common-ui";
-import WorkspaceNoticesManagementContainer from 
"../notices/WorkspaceNoticesManagementContainer.vue";
-
-const ShareButton = components.ShareButton;
-const UnsavedChangesGuard = components.UnsavedChangesGuard;
-
-type Experiment = InstanceType<typeof models.Experiment>;
-type ApplicationModule = InstanceType<typeof models.ApplicationModule>;
-type ApplicationInterfaceDefinition = InstanceType<typeof 
models.ApplicationInterfaceDefinition>;
-
-interface ProjectOption {
-  value: string;
-  text: string;
-}
-
-const props = defineProps<{
-  experiment: Experiment;
-  appModule: ApplicationModule;
-  appInterface: ApplicationInterfaceDefinition;
-}>();
-
-const emit = defineEmits<{
-  saved: [experiment: Experiment];
-  savedAndLaunched: [experiment: Experiment];
-}>();
-
-const shareButton = ref<{ mergeAndSave: (_id: string) => Promise<unknown> } | 
null>(null);
-
-const projects = ref<unknown[]>([]);
-const localExperiment = ref<Experiment>(props.experiment.clone() as 
Experiment);
-const invalidInputs = ref<string[]>([]);
-const invalidComputationalResourceSchedulingEditor = ref(false);
-const invalidGroupResourceProfileSelector = ref(false);
-const edited = ref(false);
-const saved_ = ref(false);
-const uploadingInputs = ref<string[]>([]);
-
-const sharedProjectOptions = computed<ProjectOption[]>(() =>
-  (projects.value as Array<Record<string, unknown>>)
-    .filter((p) => !p.is_owner)
-    .map((project) => ({
-      value: project.project_id as string,
-      text: project.name + (!project.is_owner ? " (owned by " + project.owner 
+ ")" : ""),
-    })),
-);
-
-const myProjectOptions = computed<ProjectOption[]>(() =>
-  (projects.value as Array<Record<string, unknown>>)
-    .filter((p) => p.is_owner)
-    .map((project) => ({
-      value: project.project_id as string,
-      text: project.name as string,
-    })),
-);
-
-const valid = computed(() => {
-  const validation = localExperiment.value.validate();
-  return (
-    Object.keys(validation).length === 0 &&
-    invalidInputs.value.length === 0 &&
-    !invalidComputationalResourceSchedulingEditor.value &&
-    !invalidGroupResourceProfileSelector.value
-  );
-});
-
-const isSaveDisabled = computed(() => !valid.value || 
hasUploadingInputs.value);
-
-const dirty = computed(() => edited.value && !saved_.value);
-
-const hasUploadingInputs = computed(() => uploadingInputs.value.length > 0);
-
-watch(
-  () => props.experiment,
-  (newValue) => {
-    localExperiment.value = newValue.clone() as Experiment;
-  },
-);
-
-watch(
-  localExperiment,
-  () => {
-    edited.value = true;
-  },
-  { deep: true },
-);
-
-watch(
-  () => (props.experiment as unknown as Record<string, 
unknown>).experiment_inputs,
-  () => {
-    experimentInputsChanged();
-  },
-  { deep: true },
-);
-
-watch(
-  () => {
-    const ucd = (props.experiment as unknown as {
-      user_configuration_data?: {
-        computational_resource_scheduling?: { resource_host_id?: string };
-      };
-    }).user_configuration_data;
-    return ucd?.computational_resource_scheduling?.resource_host_id;
-  },
-  () => {
-    resourceHostIdChanged();
-  },
-);
-
-onMounted(() => {
-  services.ProjectService.listAll().then((projs: unknown) => {
-    projects.value = projs as unknown[];
-    if (!localExperiment.value.project_id) {
-      services.WorkspacePreferencesService.get().then((workspacePreferences: 
unknown) => {
-        const prefs = workspacePreferences as Record<string, unknown>;
-        if (!localExperiment.value.project_id) {
-          localExperiment.value.project_id = prefs.most_recent_project_id as 
string;
-        }
-      });
-    }
-  });
-});
-
-function saveExperiment() {
-  return saveOrUpdateExperiment().then((experiment: Experiment) => {
-    localExperiment.value = experiment;
-    emit("saved", experiment);
-  });
-}
-
-function saveAndLaunchExperiment() {
-  return saveOrUpdateExperiment().then((experiment: Experiment) => {
-    localExperiment.value = experiment;
-    return services.ExperimentService.launch({
-      lookup: experiment.experiment_id,
-    }).then(() => {
-      emit("savedAndLaunched", experiment);
-    });
-  });
-}
-
-function saveOrUpdateExperiment(): Promise<Experiment> {
-  if (localExperiment.value.experiment_id) {
-    return services.ExperimentService.update({
-      lookup: localExperiment.value.experiment_id,
-      data: localExperiment.value,
-    }).then((experiment: unknown) => {
-      saved_.value = true;
-      return experiment as Experiment;
-    });
-  } else {
-    return services.ExperimentService.create({
-      data: localExperiment.value,
-    }).then((experiment: unknown) => {
-      const exp = experiment as Experiment;
-      saved_.value = true;
-      return shareButton.value!
-        .mergeAndSave(exp.experiment_id)
-        .then(() => exp);
-    });
-  }
-}
-
-function getValidationFeedback(properties: string): unknown {
-  return utils.getProperty(localExperiment.value.validate(), properties);
-}
-
-function getValidationState(properties: string): boolean | null {
-  return getValidationFeedback(properties) ? false : null;
-}
-
-function recordInvalidInputEditorValue(experimentInputName: string) {
-  if (!invalidInputs.value.includes(experimentInputName)) {
-    invalidInputs.value.push(experimentInputName);
-  }
-}
-
-function recordValidInputEditorValue(experimentInputName: string) {
-  if (invalidInputs.value.includes(experimentInputName)) {
-    const index = invalidInputs.value.indexOf(experimentInputName);
-    invalidInputs.value.splice(index, 1);
-  }
-}
-
-function uploadStart(experimentInputName: string) {
-  if (!uploadingInputs.value.includes(experimentInputName)) {
-    uploadingInputs.value.push(experimentInputName);
-  }
-}
-
-function uploadEnd(experimentInputName: string) {
-  if (uploadingInputs.value.includes(experimentInputName)) {
-    const index = uploadingInputs.value.indexOf(experimentInputName);
-    uploadingInputs.value.splice(index, 1);
-  }
-}
-
-function inputValueChanged() {
-  (localExperiment.value as unknown as { evaluateInputDependencies: () => void 
}).evaluateInputDependencies();
-}
-
-// Inline debounce wrapper for calculateQueueSettings
-let calcTimer: ReturnType<typeof setTimeout> | undefined;
-function calculateQueueSettings() {
-  clearTimeout(calcTimer);
-  calcTimer = setTimeout(async () => {
-    const queueSettingsUpdate = await 
services.QueueSettingsCalculatorService.calculate(
-      {
-        lookup: (props.appInterface as unknown as Record<string, 
unknown>).queue_settings_calculator_id,
-        data: localExperiment.value,
-      },
-      { showSpinner: false },
-    );
-    Object.assign(
-      (localExperiment.value as unknown as Record<string, unknown> & { 
user_configuration_data: Record<string, unknown> 
}).user_configuration_data.computationalResourceScheduling as object,
-      queueSettingsUpdate,
-    );
-  }, 500);
-}
-
-function experimentInputsChanged() {
-  if ((props.appInterface as unknown as Record<string, 
unknown>).queue_settings_calculator_id) {
-    calculateQueueSettings();
-  }
-}
-
-function resourceHostIdChanged() {
-  if ((props.appInterface as unknown as Record<string, 
unknown>).queue_settings_calculator_id) {
-    calculateQueueSettings();
-  }
-}
-</script>
-
-<style>
-.application-name {
-  font-size: 12px;
-}
-
-#col-exp-buttons {
-  text-align: right;
-}
-</style>
diff --git 
a/airavata-django-portal/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/experiment/GroupResourceProfileSelector.vue
 
b/airavata-django-portal/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/experiment/GroupResourceProfileSelector.vue
deleted file mode 100644
index ca3a591d4..000000000
--- 
a/airavata-django-portal/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/experiment/GroupResourceProfileSelector.vue
+++ /dev/null
@@ -1,114 +0,0 @@
-<template>
-  <div class="row">
-    <div class="col">
-      <div class="mb-3" label="Allocation" label-for="group-resource-profile">
-        <select
-          id="group-resource-profile"
-          v-model="groupResourceProfileId"
-          class="form-select"
-          required
-          @change="emitValueChanged"
-        >
-          <option :value="null" disabled>Select an allocation</option>
-          <option
-            v-for="option in groupResourceProfileOptions"
-            :key="option.value"
-            :value="option.value"
-          >
-            {{ option.text }}
-          </option>
-        </select>
-      </div>
-    </div>
-  </div>
-</template>
-
-<script setup lang="ts">
-import { ref, computed, onMounted } from "vue";
-import { services } from "django-airavata-api";
-
-interface GroupResourceProfile {
-  group_resource_profile_id: string;
-  group_resource_profile_name: string;
-}
-
-interface WorkspacePreferences {
-  most_recent_project_resource_profile_id?: string;
-}
-
-const props = defineProps<{
-  modelValue?: string | null;
-}>();
-
-const emit = defineEmits<{
-  "update:modelValue": [value: string | null];
-  valid: [];
-  invalid: [];
-}>();
-
-const groupResourceProfileId = ref<string | null>(props.modelValue ?? null);
-const groupResourceProfiles = ref<GroupResourceProfile[]>([]);
-const workspacePreferences = ref<WorkspacePreferences | null>(null);
-
-const groupResourceProfileOptions = computed(() => {
-  if (groupResourceProfiles.value.length > 0) {
-    const options = groupResourceProfiles.value.map((grp) => ({
-      value: grp.group_resource_profile_id,
-      text: grp.group_resource_profile_name,
-    }));
-    options.sort((a, b) => a.text.localeCompare(b.text));
-    return options;
-  }
-  return [];
-});
-
-const valid = computed(() => !!groupResourceProfileId.value);
-
-function emitValueChanged() {
-  validate();
-  emit("update:modelValue", groupResourceProfileId.value);
-}
-
-function validate() {
-  if (!valid.value) {
-    emit("invalid");
-  } else {
-    emit("valid");
-  }
-}
-
-function selectedValueInGroupResourceProfileList(profiles: 
GroupResourceProfile[]) {
-  return profiles.map((grp) => 
grp.group_resource_profile_id).indexOf(props.modelValue ?? "") >= 0;
-}
-
-function loadGroupResourceProfiles() {
-  return services.ProjectResourceProfileService.list().then(
-    (profiles: GroupResourceProfile[]) => {
-      groupResourceProfiles.value = profiles;
-      if (
-        (!props.modelValue || 
!selectedValueInGroupResourceProfileList(profiles)) &&
-        groupResourceProfiles.value.length > 0
-      ) {
-        // automatically select the last one user selected
-        groupResourceProfileId.value =
-          workspacePreferences.value?.most_recent_project_resource_profile_id 
?? null;
-        emitValueChanged();
-      }
-    },
-  );
-}
-
-function loadWorkspacePreferences() {
-  return services.WorkspacePreferencesService.get().then(
-    (prefs: WorkspacePreferences) => (workspacePreferences.value = prefs),
-  );
-}
-
-onMounted(async () => {
-  await loadWorkspacePreferences();
-  await loadGroupResourceProfiles();
-  validate();
-});
-</script>
-
-<style></style>
diff --git 
a/airavata-django-portal/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/experiment/QueueSettingsEditor.vue
 
b/airavata-django-portal/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/experiment/QueueSettingsEditor.vue
deleted file mode 100644
index d5255364d..000000000
--- 
a/airavata-django-portal/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/experiment/QueueSettingsEditor.vue
+++ /dev/null
@@ -1,544 +0,0 @@
-<template>
-  <div v-if="showQueueSettings">
-    <div class="row">
-      <div class="col">
-        <div :class="['card border-default', { 'border-danger': !valid, 
'is-disabled': disabled }]">
-          <a
-            class="card-link text-dark"
-            :disabled="disabled"
-            @click="showConfiguration = !showConfiguration"
-          >
-            <div class="card-body">
-              <h5 class="card-title mb-4">Settings for queue {{ 
data.queue_name }}</h5>
-              <div class="row">
-                <div class="col">
-                  <h3 class="h5 mb-0">
-                    {{ data.node_count }}
-                  </h3>
-                  <span class="text-muted text-uppercase">NODE COUNT</span>
-                </div>
-                <div class="col">
-                  <h3 class="h5 mb-0">
-                    {{ data.total_cpu_count }}
-                  </h3>
-                  <span class="text-muted text-uppercase">CORE COUNT</span>
-                </div>
-                <div class="col">
-                  <h3 class="h5 mb-0">{{ data.wall_time_limit }} minutes</h3>
-                  <span class="text-muted text-uppercase">TIME LIMIT</span>
-                </div>
-                <div v-if="maxPhysicalMemory > 0" class="col">
-                  <h3 class="h5 mb-0">{{ data.total_physical_memory }} MB</h3>
-                  <span class="text-muted text-uppercase">PHYSICAL 
MEMORY</span>
-                </div>
-              </div>
-            </div>
-          </a>
-        </div>
-      </div>
-    </div>
-    <div v-if="showConfiguration">
-      <div class="row">
-        <div class="col">
-          <form-group
-            label="Select a Queue"
-            label-for="queue"
-            :invalid-feedback="getValidationFeedback('queue_name')"
-            :state="getValidationState('queue_name')"
-          >
-            <select
-              id="queue"
-              v-model="data.queue_name"
-              class="form-select"
-              required
-              @change="queueChanged"
-            >
-              <option v-for="opt in queueOptions" :key="opt.value" 
:value="opt.value">
-                {{ opt.text }}
-              </option>
-            </select>
-            <small class="form-text text-muted">{{ queueDescription }}</small>
-          </form-group>
-        </div>
-        <div class="d-flex flex-row">
-          <div class="flex-fill">
-            <form-group
-              label="Node Count"
-              label-for="node-count"
-              :invalid-feedback="getValidationFeedback('nodeCount')"
-              :state="getValidationState('nodeCount', true)"
-            >
-              <input
-                id="node-count"
-                v-model="data.node_count"
-                class="form-control"
-                type="number"
-                min="1"
-                :max="maxNodes"
-                required
-                @input="nodeCountChanged"
-              />
-              <small class="form-text text-muted">
-                <i class="fa fa-info-circle" aria-hidden="true"></i>
-                Max Allowed Nodes = {{ maxNodes }}
-              </small>
-            </form-group>
-          </div>
-          <div class="flex-fill">
-            <form-group
-              label="Total Core Count"
-              label-for="core-count"
-              :invalid-feedback="getValidationFeedback('totalCPUCount')"
-              :state="getValidationState('totalCPUCount', true)"
-            >
-              <input
-                id="core-count"
-                v-model="data.total_cpu_count"
-                class="form-control"
-                type="number"
-                min="1"
-                :max="maxCPUCount"
-                required
-                @input="cpuCountChanged"
-              />
-              <small class="form-text text-muted">
-                <i class="fa fa-info-circle" aria-hidden="true"></i>
-                Max Allowed Cores = {{ maxCPUCount
-                }}<template v-if="selectedQueueDefault && 
selectedQueueDefault.cpu_per_node > 0"
-                  >. There are {{ selectedQueueDefault.cpu_per_node }} cores 
per node.
-                </template>
-              </small>
-            </form-group>
-          </div>
-        </div>
-        <div
-          v-if="selectedQueueDefault && selectedQueueDefault.cpu_per_node > 0"
-          class="d-flex flex-column"
-        >
-          <div
-            class="flex-fill"
-            style="
-              border: 1px solid #6c757d;
-              border-top-right-radius: 10px;
-              margin-top: 51px;
-              border-left-width: 0px;
-              border-bottom-width: 0px;
-              margin-right: 15px;
-            "
-          ></div>
-          <button
-            class="btn btn-sm btn-outline-secondary rounded-pill"
-            @click="enableNodeCountToCpuCheck = !enableNodeCountToCpuCheck"
-          >
-            <i v-if="enableNodeCountToCpuCheck" class="fa fa-lock" 
aria-hidden="true"></i>
-            <i v-else class="fa fa-unlock" aria-hidden="true"></i>
-          </button>
-          <div
-            class="flex-fill"
-            style="
-              border: 1px solid #6c757d;
-              border-bottom-right-radius: 10px;
-              margin-bottom: 57px;
-              border-left-width: 0px;
-              border-top-width: 0px;
-              margin-right: 15px;
-            "
-          ></div>
-        </div>
-      </div>
-      <form-group
-        label="Wall Time Limit"
-        label-for="walltime-limit"
-        :invalid-feedback="getValidationFeedback('wallTimeLimit')"
-        :state="getValidationState('wallTimeLimit', true)"
-      >
-        <div class="input-group">
-          <input
-            id="walltime-limit"
-            v-model="data.wall_time_limit"
-            class="form-control"
-            type="number"
-            min="1"
-            :max="maxWalltime"
-            required
-          />
-          <span class="input-group-text">minutes</span>
-        </div>
-        <small class="form-text text-muted">
-          <i class="fa fa-info-circle" aria-hidden="true"></i>
-          Max Allowed Wall Time = {{ maxWalltime }} minutes
-        </small>
-      </form-group>
-      <form-group
-        v-if="maxPhysicalMemory > 0"
-        label="Total Physical Memory"
-        label-for="total-physical-memory"
-        :invalid-feedback="getValidationFeedback('totalPhysicalMemory')"
-        :state="getValidationState('totalPhysicalMemory', true)"
-      >
-        <div class="input-group">
-          <input
-            id="total-physical-memory"
-            v-model="data.total_physical_memory"
-            class="form-control"
-            type="number"
-            min="0"
-            :max="maxPhysicalMemory"
-          />
-          <span class="input-group-text">MB</span>
-        </div>
-        <small class="form-text text-muted">
-          <i class="fa fa-info-circle" aria-hidden="true"></i>
-          Max Physical Memory = {{ maxPhysicalMemory }} MB
-        </small>
-      </form-group>
-      <div>
-        <a class="text-secondary action-link" href="#" 
@click.prevent="showConfiguration = false">
-          <i class="fa fa-times text-secondary" aria-hidden="true"></i>
-          Hide Settings</a
-        >
-      </div>
-    </div>
-  </div>
-</template>
-
-<script setup lang="ts">
-import { ref, computed, watch, onMounted } from "vue";
-import { models, services } from "django-airavata-api";
-import { utils } from "django-airavata-common-ui";
-
-type ComputationalResourceSchedulingModel = InstanceType<typeof 
models.ComputationalResourceSchedulingModel>;
-type ComputeResourcePolicy = InstanceType<typeof models.ComputeResourcePolicy>;
-
-interface QueueDefault {
-  queue_name: string;
-  queue_description?: string;
-  max_processors: number;
-  max_nodes: number;
-  max_run_time: number;
-  max_memory: number;
-  default_cpu_count: number;
-  default_node_count: number;
-  default_walltime: number;
-  is_default_queue: boolean;
-  cpu_per_node: number;
-}
-
-interface BatchQueueResourcePolicy {
-  queuename: string;
-  maxAllowedCores: number;
-  maxAllowedNodes: number;
-  maxAllowedWalltime: number;
-  resourcePolicyId?: string;
-}
-
-interface ApplicationInterface {
-  show_queue_settings: boolean;
-  queue_settings_calculator_id?: string;
-}
-
-const props = defineProps<{
-  modelValue: ComputationalResourceSchedulingModel;
-  appDeploymentId: string;
-  appModuleId: string;
-  computeResourcePolicy?: ComputeResourcePolicy | null;
-  batchQueueResourcePolicies?: BatchQueueResourcePolicy[] | null;
-}>();
-
-const emit = defineEmits<{
-  "update:modelValue": [value: ComputationalResourceSchedulingModel];
-  valid: [];
-  invalid: [];
-  input: [value: ComputationalResourceSchedulingModel];
-}>();
-
-// VModelMixin inline
-function copyValue(value: ComputationalResourceSchedulingModel) {
-  return value instanceof models.BaseModel ? (value as unknown as { clone: () 
=> ComputationalResourceSchedulingModel }).clone() : value;
-}
-
-const data = 
ref<ComputationalResourceSchedulingModel>(copyValue(props.modelValue));
-
-watch(
-  () => props.modelValue,
-  (newValue) => {
-    data.value = copyValue(newValue);
-  },
-  { deep: true },
-);
-
-watch(
-  data,
-  (newValue, oldValue) => {
-    if (typeof props.modelValue === "object" && newValue === oldValue) {
-      emit("update:modelValue", newValue);
-      emit("input", newValue);
-    } else if (
-      (props.modelValue === null || typeof props.modelValue !== "object") &&
-      newValue !== oldValue
-    ) {
-      emit("update:modelValue", newValue);
-      emit("input", newValue);
-    }
-  },
-  { deep: true },
-);
-
-const showConfiguration = ref(false);
-const appDeploymentQueues = ref<QueueDefault[] | null>(null);
-const enableNodeCountToCpuCheck = ref(true);
-const applicationInterface = ref<ApplicationInterface | null>(null);
-
-const queueOptions = computed(() =>
-  queueDefaults.value.map((queueDefault) => ({
-    value: queueDefault.queue_name,
-    text: queueDefault.queue_name,
-  })),
-);
-
-const selectedQueueDefault = computed<QueueDefault | undefined>(() =>
-  queueDefaults.value.find((queue) => queue.queue_name === 
data.value.queue_name),
-);
-
-const batchQueueResourcePolicyComputed = computed<BatchQueueResourcePolicy | 
null>(() => {
-  if (!selectedQueueDefault.value) return null;
-  return getBatchQueueResourcePolicy(selectedQueueDefault.value.queue_name);
-});
-
-const maxCPUCount = computed<number>(() => {
-  if (!selectedQueueDefault.value) return 0;
-  const bqrp = batchQueueResourcePolicyComputed.value;
-  if (bqrp) {
-    return Math.min(bqrp.maxAllowedCores, 
selectedQueueDefault.value.max_processors);
-  }
-  return selectedQueueDefault.value.max_processors;
-});
-
-const maxNodes = computed<number>(() => {
-  if (!selectedQueueDefault.value) return 0;
-  const bqrp = batchQueueResourcePolicyComputed.value;
-  if (bqrp) {
-    return Math.min(bqrp.maxAllowedNodes, 
selectedQueueDefault.value.max_nodes);
-  }
-  return selectedQueueDefault.value.max_nodes;
-});
-
-const maxWalltime = computed<number>(() => {
-  if (!selectedQueueDefault.value) return 0;
-  const bqrp = batchQueueResourcePolicyComputed.value;
-  if (bqrp) {
-    return Math.min(bqrp.maxAllowedWalltime, 
selectedQueueDefault.value.max_run_time);
-  }
-  return selectedQueueDefault.value.max_run_time;
-});
-
-const maxPhysicalMemory = computed<number>(() =>
-  selectedQueueDefault.value ? selectedQueueDefault.value.max_memory : 0,
-);
-
-const queueDefaults = computed<QueueDefault[]>(() => {
-  if (!appDeploymentQueues.value) return [];
-  return appDeploymentQueues.value
-    .filter((q) => isQueueInComputeResourcePolicy(q.queue_name))
-    .sort((a, b) => {
-      if (a.is_default_queue) return -1;
-      if (b.is_default_queue) return 1;
-      return a.queue_name.localeCompare(b.queue_name);
-    });
-});
-
-const validation = computed(() => {
-  if (!selectedQueueDefault.value) {
-    return data.value.validate();
-  }
-  return data.value.validate(selectedQueueDefault.value, 
batchQueueResourcePolicyComputed.value);
-});
-
-const valid = computed(() => Object.keys(validation.value).length === 0);
-
-const showQueueSettings = computed<boolean>(() =>
-  applicationInterface.value ? applicationInterface.value.show_queue_settings 
: false,
-);
-
-const disabled = computed<boolean>(
-  () => !!(applicationInterface.value && 
applicationInterface.value.queue_settings_calculator_id),
-);
-
-const queueDescription = computed<string | null>(() =>
-  selectedQueueDefault.value ? (selectedQueueDefault.value.queue_description 
?? null) : null,
-);
-
-watch(enableNodeCountToCpuCheck, () => {
-  if (enableNodeCountToCpuCheck.value) {
-    nodeCountChanged();
-  }
-});
-
-watch(
-  () => props.appDeploymentId,
-  () => {
-    loadAppDeploymentQueues().then(() => setDefaultQueue());
-  },
-);
-
-watch(batchQueueResourcePolicyComputed, (value, oldValue) => {
-  if (value && (!oldValue || value.resourcePolicyId !== 
oldValue.resourcePolicyId)) {
-    applyBatchQueueResourcePolicy();
-  }
-});
-
-watch(
-  () => props.computeResourcePolicy,
-  () => {
-    if (!isQueueInComputeResourcePolicy(data.value.queue_name)) {
-      setDefaultQueue();
-    }
-  },
-);
-
-watch(
-  () => props.modelValue,
-  () => {
-    validate();
-  },
-  { deep: true },
-);
-
-onMounted(() => {
-  loadAppDeploymentQueues().then(() => {
-    if (!props.modelValue.queue_name) {
-      setDefaultQueue();
-    }
-  });
-  validate();
-  loadApplicationInterface();
-});
-
-function queueChanged(event: Event) {
-  const queueName = (event.target as HTMLSelectElement).value;
-  const queueDefault = queueDefaults.value.find((queue) => queue.queue_name 
=== queueName);
-  if (queueDefault) {
-    data.value.total_cpu_count = getDefaultCPUCount(queueDefault);
-    data.value.node_count = getDefaultNodeCount(queueDefault);
-    data.value.wall_time_limit = getDefaultWalltime(queueDefault);
-    if (maxPhysicalMemory.value === 0) {
-      data.value.total_physical_memory = 0;
-    }
-  }
-}
-
-function validate() {
-  if (!valid.value) {
-    emit("invalid");
-  } else {
-    emit("valid");
-  }
-}
-
-function loadAppDeploymentQueues(): Promise<void> {
-  return services.ApplicationDeploymentService.getQueues({
-    lookup: props.appDeploymentId,
-  }).then((queueDefaults: unknown) => {
-    appDeploymentQueues.value = queueDefaults as QueueDefault[];
-  });
-}
-
-function setDefaultQueue() {
-  if (queueDefaults.value.length === 0) {
-    data.value.queue_name = null;
-    return;
-  }
-  const defaultQueue = queueDefaults.value[0];
-  data.value.queue_name = defaultQueue.queue_name;
-  data.value.total_cpu_count = getDefaultCPUCount(defaultQueue);
-  data.value.node_count = getDefaultNodeCount(defaultQueue);
-  data.value.wall_time_limit = getDefaultWalltime(defaultQueue);
-  if (maxPhysicalMemory.value === 0) {
-    data.value.total_physical_memory = 0;
-  }
-}
-
-function isQueueInComputeResourcePolicy(queue_name: string): boolean {
-  if (!props.computeResourcePolicy) return true;
-  return (props.computeResourcePolicy as unknown as { allowedBatchQueues: 
string[] }).allowedBatchQueues.includes(queue_name);
-}
-
-function getBatchQueueResourcePolicy(queueName: string): 
BatchQueueResourcePolicy | null {
-  if (!props.batchQueueResourcePolicies || 
props.batchQueueResourcePolicies.length === 0) {
-    return null;
-  }
-  return props.batchQueueResourcePolicies.find((bqrp) => bqrp.queuename === 
queueName) ?? null;
-}
-
-function getDefaultCPUCount(queueDefault: QueueDefault): number {
-  const bqrp = batchQueueResourcePolicyComputed.value;
-  if (bqrp) {
-    return Math.min(bqrp.maxAllowedCores, queueDefault.default_cpu_count);
-  }
-  return queueDefault.default_cpu_count;
-}
-
-function getDefaultNodeCount(queueDefault: QueueDefault): number {
-  const bqrp = batchQueueResourcePolicyComputed.value;
-  if (bqrp) {
-    return Math.min(bqrp.maxAllowedNodes, queueDefault.default_node_count);
-  }
-  return queueDefault.default_node_count;
-}
-
-function getDefaultWalltime(queueDefault: QueueDefault): number {
-  const bqrp = batchQueueResourcePolicyComputed.value;
-  if (bqrp) {
-    return Math.min(bqrp.maxAllowedWalltime, queueDefault.default_walltime);
-  }
-  return queueDefault.default_walltime;
-}
-
-function getValidationFeedback(properties: string): unknown {
-  return utils.getProperty(validation.value, properties);
-}
-
-function getValidationState(properties: string, showValidState?: boolean): 
boolean | null {
-  return getValidationFeedback(properties) ? false : showValidState ? true : 
null;
-}
-
-function applyBatchQueueResourcePolicy() {
-  if (selectedQueueDefault.value) {
-    data.value.total_cpu_count = Math.min(data.value.total_cpu_count, 
maxCPUCount.value);
-    data.value.node_count = Math.min(data.value.node_count, maxNodes.value);
-    data.value.wall_time_limit = Math.min(data.value.wall_time_limit, 
maxWalltime.value);
-  }
-}
-
-function nodeCountChanged() {
-  if (enableNodeCountToCpuCheck.value && selectedQueueDefault.value && 
selectedQueueDefault.value.cpu_per_node > 0) {
-    const nodeCount = parseInt(String(data.value.node_count));
-    data.value.total_cpu_count = Math.min(
-      nodeCount * selectedQueueDefault.value.cpu_per_node,
-      maxCPUCount.value,
-    );
-  }
-}
-
-function cpuCountChanged() {
-  if (enableNodeCountToCpuCheck.value && selectedQueueDefault.value && 
selectedQueueDefault.value.cpu_per_node > 0) {
-    const cpuCount = parseInt(String(data.value.total_cpu_count));
-    if (cpuCount > 0) {
-      data.value.node_count = Math.min(
-        Math.ceil(cpuCount / selectedQueueDefault.value.cpu_per_node),
-        maxNodes.value,
-      );
-    }
-  }
-}
-
-function loadApplicationInterface() {
-  services.ApplicationModuleService.getApplicationInterface({
-    lookup: props.appModuleId,
-  }).then((iface: unknown) => {
-    applicationInterface.value = iface as ApplicationInterface;
-  });
-}
-</script>
-
-<style></style>
diff --git 
a/airavata-django-portal/django_airavata/apps/workspace/static/django_airavata_workspace/js/containers/CreateExperimentContainer.vue
 
b/airavata-django-portal/django_airavata/apps/workspace/static/django_airavata_workspace/js/containers/CreateExperimentContainer.vue
deleted file mode 100644
index 7a0bfcaac..000000000
--- 
a/airavata-django-portal/django_airavata/apps/workspace/static/django_airavata_workspace/js/containers/CreateExperimentContainer.vue
+++ /dev/null
@@ -1,99 +0,0 @@
-<template>
-  <experiment-editor
-    v-if="experiment"
-    :experiment="experiment"
-    :app-module="appModule"
-    :app-interface="appInterface"
-    @saved="handleSavedExperiment"
-    @saved-and-launched="handleSavedAndLaunchedExperiment"
-  >
-    <template #title>
-      <span>Create a New Experiment</span>
-    </template>
-  </experiment-editor>
-</template>
-
-<script setup lang="ts">
-import { ref, onMounted } from "vue";
-import { services } from "django-airavata-api";
-import { notifications } from "django-airavata-common-ui";
-import ExperimentEditor from "../components/experiment/ExperimentEditor.vue";
-import urls from "../utils/urls";
-
-import { formatShort } from "django-airavata-common-ui/js/utils/dates.js";
-
-const props = defineProps<{
-  appModuleId?: string;
-  userInputValues?: Record<string, unknown> | null;
-  experimentDataDir?: string | null;
-}>();
-
-// Convenience accessors
-const appModuleId = () => props.appModuleId;
-const userInputValues = () => props.userInputValues;
-const experimentDataDir = () => props.experimentDataDir;
-
-const experiment = ref<unknown>(null);
-const appModule = ref<unknown>(null);
-const appInterface = ref<unknown>(null);
-
-onMounted(() => {
-  const modId = appModuleId();
-  if (!modId) return;
-  const loadAppModule = services.ApplicationModuleService.retrieve(
-    { lookup: modId },
-    { ignoreErrors: true },
-  );
-  const loadAppInterface = 
services.ApplicationModuleService.getApplicationInterface(
-    { lookup: modId },
-    { ignoreErrors: true },
-  );
-  Promise.all([loadAppModule, loadAppInterface])
-    .then(([mod, iface]: [unknown, unknown]) => {
-      const typedMod = mod as { app_module_name: string };
-      const typedIface = iface as {
-        createExperiment(): unknown;
-      };
-      const exp = typedIface.createExperiment() as {
-        experiment_name: string;
-        experiment_inputs: Array<{ name: string; value: unknown }>;
-        user_configuration_data: { experiment_data_dir: string };
-      };
-      exp.experiment_name = typedMod.app_module_name + " on " + 
formatShort(new Date());
-      appModule.value = mod;
-      appInterface.value = iface;
-      const inputValues = userInputValues();
-      if (inputValues) {
-        Object.keys(inputValues).forEach((k) => {
-          const experimentInput = exp.experiment_inputs.find((inp) => inp.name 
=== k);
-          if (experimentInput) {
-            experimentInput.value = inputValues[k];
-          }
-        });
-      }
-      const dataDir = experimentDataDir();
-      if (dataDir) {
-        exp.user_configuration_data.experiment_data_dir = dataDir;
-      }
-      experiment.value = exp;
-    })
-    .catch((error: unknown) => {
-      notifications.NotificationList.addError(error);
-    });
-});
-
-function handleSavedExperiment() {
-  urls.navigateToExperimentsList("");
-}
-
-function handleSavedAndLaunchedExperiment(exp: unknown) {
-  urls.navigateToViewExperiment("", exp as { experiment_id: string }, { 
launching: true });
-}
-</script>
-
-<style>
-/* style the containing div, in base.html template */
-.main-content-wrapper {
-  background-color: #ffffff;
-}
-</style>
diff --git 
a/airavata-django-portal/django_airavata/apps/workspace/static/django_airavata_workspace/js/containers/EditExperimentContainer.vue
 
b/airavata-django-portal/django_airavata/apps/workspace/static/django_airavata_workspace/js/containers/EditExperimentContainer.vue
deleted file mode 100644
index a5566322c..000000000
--- 
a/airavata-django-portal/django_airavata/apps/workspace/static/django_airavata_workspace/js/containers/EditExperimentContainer.vue
+++ /dev/null
@@ -1,78 +0,0 @@
-<template>
-  <experiment-editor
-    v-if="appModule"
-    :experiment="experiment"
-    :app-module="appModule"
-    :app-interface="appInterface"
-    @saved="handleSavedExperiment"
-    @saved-and-launched="handleSavedAndLaunchedExperiment"
-  >
-    <template #title>
-      <span>Edit Experiment</span>
-    </template>
-  </experiment-editor>
-</template>
-
-<script setup lang="ts">
-import { ref, onMounted } from "vue";
-import { errors, services } from "django-airavata-api";
-import { notifications } from "django-airavata-common-ui";
-import ExperimentEditor from "../components/experiment/ExperimentEditor.vue";
-import urls from "../utils/urls";
-
-const props = defineProps<{
-  experimentId: string;
-}>();
-
-const experiment = ref<unknown>(null);
-const appModule = ref<unknown>(null);
-const appInterface = ref<unknown>(null);
-
-onMounted(() => {
-  services.ExperimentService.retrieve({ lookup: props.experimentId })
-    .then((exp: unknown) => {
-      experiment.value = exp;
-      const appInterfaceId = (exp as { execution_id: string }).execution_id;
-      return services.ApplicationInterfaceService.retrieve(
-        { lookup: appInterfaceId },
-        { ignoreErrors: true },
-      );
-    })
-    .then((iface: unknown) => {
-      appInterface.value = iface;
-      const appModuleId = (iface as { application_modules: string[] 
}).application_modules[0];
-      return services.ApplicationModuleService.retrieve({ lookup: appModuleId 
});
-    })
-    .then((mod: unknown) => {
-      appModule.value = mod;
-    })
-    .catch((error: unknown) => {
-      const exp = experiment.value as { execution_id: string } | null;
-      const message = errors.ErrorUtils.isNotFoundError(error)
-        ? `Application interface (${exp?.execution_id}) was not found.
-           If it has been deleted then you won't be able to edit this 
experiment.`
-        : `Unable to load application interface (${exp?.execution_id}) or 
module`;
-      notifications.NotificationList.add(
-        new notifications.Notification({
-          type: "ERROR",
-          message,
-        }),
-      );
-    });
-});
-
-function handleSavedExperiment() {
-  urls.navigateToExperimentsList("");
-}
-
-function handleSavedAndLaunchedExperiment(exp: unknown) {
-  urls.navigateToViewExperiment("", exp as { experiment_id: string }, { 
launching: true });
-}
-</script>
-
-<style>
-/* style the containing div, in base.html template */
-.main-content-wrapper {
-  background-color: #ffffff;
-}
-</style>
diff --git 
a/airavata-django-portal/django_airavata/apps/workspace/static/django_airavata_workspace/js/entry-create-experiment.js
 
b/airavata-django-portal/django_airavata/apps/workspace/static/django_airavata_workspace/js/entry-create-experiment.js
deleted file mode 100644
index 9d0d999b4..000000000
--- 
a/airavata-django-portal/django_airavata/apps/workspace/static/django_airavata_workspace/js/entry-create-experiment.js
+++ /dev/null
@@ -1,32 +0,0 @@
-import { h } from "vue";
-import { components, entry } from "django-airavata-common-ui";
-import CreateExperimentContainer from 
"./containers/CreateExperimentContainer.vue";
-import "../../scss/styles.scss";
-
-entry(({ createApp }) => {
-  const el = document.getElementById("create-experiment");
-  const appModuleId = el ? el.dataset.appModuleId || null : null;
-  const userInputValues =
-    el && el.dataset.userInputValues ? JSON.parse(el.dataset.userInputValues) 
: null;
-  const experimentDataDir = el ? el.dataset.experimentDataDir || null : null;
-  const app = createApp({
-    data() {
-      return {
-        appModuleId,
-        userInputValues,
-        experimentDataDir,
-      };
-    },
-    render() {
-      return h(components.MainLayout, null, {
-        default: () =>
-          h(CreateExperimentContainer, {
-            appModuleId: this.appModuleId,
-            userInputValues: this.userInputValues,
-            experimentDataDir: this.experimentDataDir,
-          }),
-      });
-    },
-  });
-  app.mount("#create-experiment");
-});
diff --git 
a/airavata-django-portal/django_airavata/apps/workspace/static/django_airavata_workspace/js/entry-edit-experiment.js
 
b/airavata-django-portal/django_airavata/apps/workspace/static/django_airavata_workspace/js/entry-edit-experiment.js
deleted file mode 100644
index 4332b258e..000000000
--- 
a/airavata-django-portal/django_airavata/apps/workspace/static/django_airavata_workspace/js/entry-edit-experiment.js
+++ /dev/null
@@ -1,25 +0,0 @@
-import { h } from "vue";
-import { components, entry } from "django-airavata-common-ui";
-import EditExperimentContainer from "./containers/EditExperimentContainer.vue";
-import "../../scss/styles.scss";
-
-entry(({ createApp }) => {
-  const el = document.getElementById("edit-experiment");
-  const experimentId = el ? el.dataset.experimentId || null : null;
-  const app = createApp({
-    data() {
-      return {
-        experimentId,
-      };
-    },
-    render() {
-      return h(components.MainLayout, null, {
-        default: () =>
-          h(EditExperimentContainer, {
-            experimentId: this.experimentId,
-          }),
-      });
-    },
-  });
-  app.mount("#edit-experiment");
-});
diff --git a/airavata-django-portal/django_airavata/apps/workspace/urls.py 
b/airavata-django-portal/django_airavata/apps/workspace/urls.py
index d493334b5..5e1218575 100644
--- a/airavata-django-portal/django_airavata/apps/workspace/urls.py
+++ b/airavata-django-portal/django_airavata/apps/workspace/urls.py
@@ -23,8 +23,8 @@ urlpatterns = [
     ),
     re_path(
         
r"^projects/(?P<project_id>[^/]+)/experiments/(?P<experiment_id>[^/]+)/edit$",
-        views.edit_experiment,
-        name="edit_experiment",
+        RedirectView.as_view(url="/workspace/launch", permanent=True),
+        name="edit_experiment_redirect",
     ),
     re_path(
         
r"^projects/(?P<project_id>[^/]+)/experiments/(?P<experiment_id>[^/]+)/$",
diff --git a/airavata-django-portal/django_airavata/apps/workspace/views.py 
b/airavata-django-portal/django_airavata/apps/workspace/views.py
index cfdf3010d..54ecdaa1a 100644
--- a/airavata-django-portal/django_airavata/apps/workspace/views.py
+++ b/airavata-django-portal/django_airavata/apps/workspace/views.py
@@ -1,22 +1,16 @@
 import json
 import logging
-from urllib.parse import urlparse
 
 from django.conf import settings
 from django.contrib.auth.decorators import login_required
 from django.shortcuts import render
-from django.utils.module_loading import import_string
 from rest_framework.renderers import JSONRenderer
 
-from django_airavata.apps.api import models
-from django_airavata.apps.api import user_storage as user_storage_sdk
 from django_airavata.apps.api.views import (
-    ApplicationModuleViewSet,
     ExperimentSearchViewSet,
     FullExperimentViewSet,
     ProjectViewSet,
 )
-from django_airavata.proto_compat import DataType
 
 logger = logging.getLogger(__name__)
 
@@ -27,8 +21,6 @@ ENTRY_POINTS = {
     "project-list": 
"static/django_airavata_workspace/js/entry-project-list.js",
     "project-overview": 
"static/django_airavata_workspace/js/entry-project-overview.js",
     "edit-project": 
"static/django_airavata_workspace/js/entry-edit-project.js",
-    "create-experiment": 
"static/django_airavata_workspace/js/entry-create-experiment.js",
-    "edit-experiment": 
"static/django_airavata_workspace/js/entry-edit-experiment.js",
     "view-experiment": 
"static/django_airavata_workspace/js/entry-view-experiment.js",
     "user-storage": 
"static/django_airavata_workspace/js/entry-user-storage.js",
     "compute": "static/django_airavata_workspace/js/entry-compute.js",
@@ -110,19 +102,6 @@ def _create_default_project(request):
     return project_id
 
 
-@login_required
-def applications(request):
-    request.active_nav_item = "applications"
-    return render(
-        request,
-        "django_airavata_workspace/base.html",
-        {
-            "bundle_name": "applications",
-            "entry_point": ENTRY_POINTS["applications"],
-        },
-    )
-
-
 @login_required
 def new_application(request):
     request.active_nav_item = "applications"
@@ -185,105 +164,6 @@ def project_overview(request, project_id):
     )
 
 
-@login_required
-def create_experiment(request, app_module_id):
-    request.active_nav_item = "applications"
-
-    # User input files can be passed as query parameters
-    # <input name>=<path/to/user_file>
-    # and also as data product URIs
-    # <input name>=<data product URI>
-    app_interface = ApplicationModuleViewSet.as_view({"get": 
"application_interface"})(
-        request, app_module_id=app_module_id
-    )
-    if app_interface.status_code != 200:
-        raise Exception("Failed to load application module data: 
{}".format(app_interface.data["detail"]))
-    user_input_values = {}
-    for app_input in app_interface.data.get("application_inputs", []):
-        if app_input["type"] == DataType.URI and app_input["name"] in 
request.GET:
-            user_file_value = request.GET[app_input["name"]]
-            try:
-                user_file_url = urlparse(user_file_value)
-                if user_file_url.scheme == "airavata-dp":
-                    dp_uri = user_file_value
-                    try:
-                        data_product = 
request.airavata_client.research.get_data_product(dp_uri)
-                        if user_storage_sdk.exists(request, data_product):
-                            user_input_values[app_input["name"]] = dp_uri
-                    except Exception:
-                        logger.exception(f"Failed checking data product uri: 
{dp_uri}", extra={"request": request})
-            except ValueError:
-                logger.exception(f"Invalid user file value: 
{user_file_value}", extra={"request": request})
-        elif app_input["type"] == DataType.STRING and app_input["name"] in 
request.GET:
-            name = app_input["name"]
-            user_input_values[name] = request.GET[name]
-    context = {
-        "bundle_name": "create-experiment",
-        "entry_point": ENTRY_POINTS["create-experiment"],
-        "app_module_id": app_module_id,
-        "user_input_values": json.dumps(user_input_values),
-    }
-    if "experiment-data-dir" in request.GET:
-        context["experiment_data_dir"] = request.GET["experiment-data-dir"]
-
-    template_path = "django_airavata_workspace/create_experiment.html"
-    # Apply a custom application template if it exists
-    custom_template_path, custom_context = get_custom_template(request, 
app_module_id)
-    if custom_template_path is not None:
-        logger.debug(f"Applying custom application template 
{custom_template_path}")
-        template_path = custom_template_path
-        context.update(custom_context)
-
-    return render(request, template_path, context)
-
-
-@login_required
-def edit_experiment(request, project_id, experiment_id):
-    request.active_nav_item = "projects"
-
-    project = request.airavata_client.research.get_project(project_id)
-    experiment = request.airavata_client.research.get_experiment(experiment_id)
-    applicationInterface = 
request.airavata_client.research.get_application_interface(experiment.execution_id)
-    app_module_id = applicationInterface.application_modules[0]
-
-    breadcrumbs = [
-        {"label": "Projects", "url": "/workspace/projects"},
-        {"label": project.name, "url": f"/workspace/projects/{project_id}/"},
-        {"label": "Experiments", "url": 
f"/workspace/projects/{project_id}/experiments"},
-        {"label": "Edit Experiment", "url": None},
-    ]
-
-    context = {
-        "bundle_name": "edit-experiment",
-        "entry_point": ENTRY_POINTS["edit-experiment"],
-        "experiment_id": experiment_id,
-        "app_module_id": app_module_id,
-        "project_id": project_id,
-        "breadcrumbs_json": json.dumps(breadcrumbs),
-    }
-    template_path = "django_airavata_workspace/edit_experiment.html"
-    custom_template_path, custom_context = get_custom_template(request, 
app_module_id)
-    if custom_template_path is not None:
-        logger.debug(f"Applying custom application template 
{custom_template_path}")
-        template_path = custom_template_path
-        context.update(custom_context)
-
-    return render(request, template_path, context)
-
-
-def get_custom_template(request, app_module_id):
-    template_path = None
-    context = {}
-    query = 
models.ApplicationTemplate.objects.filter(application_module_id=app_module_id)
-    if query.exists():
-        application_template = query.get()
-        template_path = application_template.template_path
-        for context_processor in application_template.context_processors.all():
-            context_processor = import_string(context_processor.callable_path)
-            context.update(context_processor(request))
-    return template_path, context
-
-
 @login_required
 def view_experiment(request, project_id, experiment_id):
     request.active_nav_item = "projects"
diff --git 
a/airavata-django-portal/django_airavata/apps/workspace/vite.config.js 
b/airavata-django-portal/django_airavata/apps/workspace/vite.config.js
index a73d02e6a..2d23675da 100644
--- a/airavata-django-portal/django_airavata/apps/workspace/vite.config.js
+++ b/airavata-django-portal/django_airavata/apps/workspace/vite.config.js
@@ -10,10 +10,8 @@ export default defineAppConfig({
     dashboard: resolve(srcDir, "entry-dashboard.js"),
     "project-list": resolve(srcDir, "entry-project-list.js"),
     applications: resolve(srcDir, "entry-applications.js"),
-    "create-experiment": resolve(srcDir, "entry-create-experiment.js"),
     "view-experiment": resolve(srcDir, "entry-view-experiment.js"),
     "experiment-list": resolve(srcDir, "entry-experiment-list.js"),
-    "edit-experiment": resolve(srcDir, "entry-edit-experiment.js"),
     "edit-project": resolve(srcDir, "entry-edit-project.js"),
     "user-storage": resolve(srcDir, "entry-user-storage.js"),
     compute: resolve(srcDir, "entry-compute.js"),

Reply via email to