Repository: devtron-labs/dashboard
Pull request #2705: feat: app clone flow
Author: login: shivani170
Labels: name: PR:Ready-to-Review
description: PR:Ready-to-Review
Created: 2025-05-13T14:01:54Z | Merged: 2025-05-21T11:23:34Z

# Description

To Update App clone Flow

- [x] Devtron App Clone Modification
- [x] Job Icon Replacement

<img width="1034" alt="Screenshot 2025-05-16 at 3 38 41 PM" src="https://github.com/user-attachments/assets/76c690c9-dfed-44a9-abbd-fbf777a2fb00" />


Fixes https://github.com/devtron-labs/sprint-tasks/issues/2194

## Type of change

- [ ] Bug fix (non-breaking change which fixes an issue)
- [x] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] This change requires a documentation update


# Checklist:

* [x] The title of the PR states what changed and the related issues number (used for the release note).
* [ ] Does this PR require documentation updates?
* [ ] I've updated documentation as required by this PR.
* [ ] I have performed a self-review of my own code
* [x] I have commented my code, particularly in hard-to-understand areas





Diff:
diff --git a/package.json b/package.json
index 8f4b992386..cf78b70f28 100644
--- a/package.json
+++ b/package.json
@@ -4,7 +4,7 @@
     "private": true,
     "homepage": "/dashboard",
     "dependencies": {
-        "@devtron-labs/devtron-fe-common-lib": "1.13.0-pre-6",
+        "@devtron-labs/devtron-fe-common-lib": "1.13.0-pre-9",
         "@esbuild-plugins/node-globals-polyfill": "0.2.3",
         "@rjsf/core": "^5.13.3",
         "@rjsf/utils": "^5.13.3",
diff --git a/src/Pages/App/CreateAppModal/AppClone/AppCloneList.tsx b/src/Pages/App/CreateAppModal/AppClone/AppCloneList.tsx
new file mode 100644
index 0000000000..ffa22ee1ba
--- /dev/null
+++ b/src/Pages/App/CreateAppModal/AppClone/AppCloneList.tsx
@@ -0,0 +1,81 @@
+import {
+    Button,
+    ComponentSizeType,
+    DetectBottom,
+    GenericInfoCardBorderVariant,
+    GenericInfoCardListing,
+    GenericInfoListSkeleton,
+    Icon,
+    SearchBar,
+    useStateFilters,
+} from '@devtron-labs/devtron-fe-common-lib'
+
+import { CreationMethodType } from '../types'
+import { AppCloneListProps } from './types'
+import { useDevtronCloneList } from './useDevtronCloneList'
+
+export const AppCloneList = ({ handleCloneAppClick, isJobView, handleCreationMethodChange }: AppCloneListProps) => {
+    const { searchKey, handleSearch, clearFilters } = useStateFilters()
+
+    const { isListLoading, list, listError, reloadList, loadMoreData, hasMoreData, isLoadingMore, hasError } =
+        useDevtronCloneList({
+            handleCloneAppClick,
+            isJobView,
+            searchKey,
+        })
+
+    const handleLoadMore = async () => {
+        if (isLoadingMore || !hasMoreData) return
+        await loadMoreData()
+    }
+
+    const handleCreateFromScratch = () => {
+        handleCreationMethodChange(CreationMethodType.blank)
+    }
+
+    const renderCreateFromScratchButton = () => (
+        <Button
+            dataTestId="create-app-modal-create-from-scratch-btn"
+            text="Create from scratch"
+            onClick={handleCreateFromScratch}
+            startIcon={<Icon name="ic-new" color={null} />}
+        />
+    )
+
+    return (
+        <div className="flex-grow-1 flexbox-col dc__overflow-auto">
+            <div className="flexbox-col dc__gap-12 pt-20 px-20">
+                <h2 className="m-0 fs-15 lh-1-5 fw-6 cn-9">Choose {isJobView ? 'a job' : 'an application'} to clone</h2>
+
+                <SearchBar
+                    dataTestId="template-list-search"
+                    initialSearchText={searchKey}
+                    size={ComponentSizeType.medium}
+                    handleEnter={handleSearch}
+                    inputProps={{
+                        placeholder: `Search ${isJobView ? 'job' : 'application'}`,
+                    }}
+                />
+            </div>
+            <div className="flex-grow-1 flexbox-col dc__gap-12 p-20 dc__overflow-auto">
+                <GenericInfoCardListing
+                    borderVariant={GenericInfoCardBorderVariant.ROUNDED}
+                    list={list}
+                    searchKey={searchKey}
+                    isLoading={isListLoading}
+                    error={listError}
+                    reloadList={reloadList}
+                    handleClearFilters={clearFilters}
+                    emptyStateConfig={{
+                        title: 'Nothing to Clone… Yet!',
+                        subTitle: `You haven’t created any ${isJobView ? 'job' : 'application'} to clone. Kick things off by crafting one from scratch—it’s quick and easy!`,
+                        renderButton: renderCreateFromScratchButton,
+                    }}
+                />
+                {hasMoreData && isLoadingMore && <GenericInfoListSkeleton />}
+
+                {hasMoreData && !isLoadingMore && <DetectBottom callback={handleLoadMore} hasError={hasError} />}
+            </div>
+        </div>
+    )
+}
diff --git a/src/Pages/App/CreateAppModal/AppClone/index.ts b/src/Pages/App/CreateAppModal/AppClone/index.ts
new file mode 100644
index 0000000000..40234bde4d
--- /dev/null
+++ b/src/Pages/App/CreateAppModal/AppClone/index.ts
@@ -0,0 +1,2 @@
+export * from './AppCloneList'
+export { useDevtronCloneList } from './useDevtronCloneList'
diff --git a/src/Pages/App/CreateAppModal/AppClone/types.ts b/src/Pages/App/CreateAppModal/AppClone/types.ts
new file mode 100644
index 0000000000..892afa2f2e
--- /dev/null
+++ b/src/Pages/App/CreateAppModal/AppClone/types.ts
@@ -0,0 +1,28 @@
+import { BaseAppMetaData, GenericInfoCardListingProps } from '@devtron-labs/devtron-fe-common-lib'
+
+import { APP_TYPE } from '@Config/constants'
+
+import { SidebarProps } from '../types'
+
+export interface AppCloneListProps extends Pick<SidebarProps, 'handleCreationMethodChange'> {
+    handleCloneAppClick: ({ appId, appName }: BaseAppMetaData) => void
+    isJobView?: boolean
+}
+
+export type CloneListResponse = {
+    type: APP_TYPE.DEVTRON_APPS | APP_TYPE.JOB
+    list: GenericInfoCardListingProps['list']
+    totalCount: number
+}
+
+export interface CloneListTypes {
+    offset?: number
+    isJobView?: boolean
+    searchKey?: string
+    cloneListAbortControllerRef: React.MutableRefObject<AbortController>
+    handleCloneAppClick: (app: BaseAppMetaData) => void
+}
+
+export interface DevtronAppCloneListProps extends Pick<AppCloneListProps, 'handleCloneAppClick' | 'isJobView'> {
+    searchKey: string
+}
diff --git a/src/Pages/App/CreateAppModal/AppClone/useDevtronCloneList.tsx b/src/Pages/App/CreateAppModal/AppClone/useDevtronCloneList.tsx
new file mode 100644
index 0000000000..6c01e19245
--- /dev/null
+++ b/src/Pages/App/CreateAppModal/AppClone/useDevtronCloneList.tsx
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2024. Devtron Inc.
+ */
+import { useEffect, useRef, useState } from 'react'
+
+import { getIsRequestAborted, showError, useAsync } from '@devtron-labs/devtron-fe-common-lib'
+
+import { APP_TYPE } from '@Config/constants'
+
+import { fetchDevtronCloneList } from '../service'
+import { DevtronAppCloneListProps } from './types'
+
+export const useDevtronCloneList = ({ handleCloneAppClick, isJobView, searchKey }: DevtronAppCloneListProps) => {
+    const cloneListAbortControllerRef = useRef(new AbortController())
+    const [isLoadingMore, setIsLoadingMore] = useState(false)
+    const [hasError, setHasError] = useState(false)
+
+    useEffect(
+        () => () => {
+            cloneListAbortControllerRef.current.abort()
+        },
+        [],
+    )
+
+    const [isListLoading, listResponse, listError, reloadList, setListResponse] = useAsync(() =>
+        fetchDevtronCloneList({
+            isJobView,
+            searchKey,
+            cloneListAbortControllerRef,
+            handleCloneAppClick,
+        }),
+    )
+
+    const loadMoreData = async () => {
+        if (isLoadingMore || !listResponse) return
+
+        setIsLoadingMore(true)
+        try {
+            if (listResponse.type === APP_TYPE.JOB) {
+                const currentList = listResponse.list
+
+                const response = await fetchDevtronCloneList({
+                    isJobView,
+                    searchKey,
+                    offset: currentList.length,
+                    cloneListAbortControllerRef,
+                    handleCloneAppClick,
+                })
+
+                setListResponse({
+                    ...response,
+                    list: [...currentList, ...response.list],
+                })
+            }
+        } catch (error) {
+            setHasError(true)
+            showError(error)
+        } finally {
+            setIsLoadingMore(false)
+        }
+    }
+
+    return {
+        isListLoading: isListLoading || getIsRequestAborted(listError),
+        list: listResponse?.list ?? [],
+        listError,
+        reloadList,
+        totalCount: listResponse?.totalCount ?? 0,
+        loadMoreData,
+        hasMoreData: listResponse?.type === APP_TYPE.JOB && (listResponse.list?.length ?? 0) < listResponse.totalCount,
+        hasError,
+        isLoadingMore,
+    }
+}
diff --git a/src/Pages/App/CreateAppModal/AppToCloneSelector.tsx b/src/Pages/App/CreateAppModal/AppToCloneSelector.tsx
deleted file mode 100644
index 1d99162b7d..0000000000
--- a/src/Pages/App/CreateAppModal/AppToCloneSelector.tsx
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (c) 2024. Devtron Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import { useState } from 'react'
-
-import {
-    AppSelectorNoOptionsMessage as appSelectorNoOptionsMessage,
-    ComponentSizeType,
-    InfoBlock,
-    SelectPicker,
-    SelectPickerProps,
-} from '@devtron-labs/devtron-fe-common-lib'
-
-import { appListOptions } from '@Components/AppSelector/AppSelectorUtil'
-
-import { AppToCloneSelectorProps } from './types'
-
-const AppToCloneSelector = ({ isJobView, error, handleCloneIdChange }: AppToCloneSelectorProps) => {
-    const [inputValue, setInputValue] = useState('')
-    const [areOptionsLoading, setAreOptionsLoading] = useState(false)
-    const [options, setOptions] = useState([])
-
-    const onInputChange: SelectPickerProps['onInputChange'] = async (val) => {
-        setInputValue(val)
-        setAreOptionsLoading(true)
-        const fetchedOptions = await appListOptions({ inputValue: val, isJobView })
-        setAreOptionsLoading(false)
-        setOptions(fetchedOptions)
-    }
-
-    const onChange = (selectedClonedApp) => {
-        handleCloneIdChange(selectedClonedApp.value)
-    }
-
-    const noOptionsMessage: SelectPickerProps['noOptionsMessage'] = () =>
-        appSelectorNoOptionsMessage({
-            inputValue,
-        })
-
-    return (
-        <>
-            <SelectPicker
-                label={`Select an ${isJobView ? 'job' : 'app'} to clone`}
-                inputId={`${isJobView ? 'job' : 'app'}-name-for-clone`}
-                options={options}
-                onChange={onChange}
-                placeholder={`Select ${isJobView ? 'job' : 'app'}`}
-                inputValue={inputValue}
-                onInputChange={onInputChange}
-                isLoading={areOptionsLoading}
-                noOptionsMessage={noOptionsMessage}
-                error={error}
-                size={ComponentSizeType.large}
-            />
-            <InfoBlock
-                heading="Important:"
-                description={
-                    isJobView
-                        ? 'Do not forget to modify git repositories and corresponding branches to be used for each Job Pipeline if required.'
-                        : 'Do not forget to modify git repositories, corresponding branches and container registries to be used for each CI Pipeline if required.'
-                }
-            />
-        </>
-    )
-}
-
-export default AppToCloneSelector
diff --git a/src/Pages/App/CreateAppModal/ApplicationInfoForm.tsx b/src/Pages/App/CreateAppModal/ApplicationInfoForm.tsx
index 9c94c47315..2a44994e05 100644
--- a/src/Pages/App/CreateAppModal/ApplicationInfoForm.tsx
+++ b/src/Pages/App/CreateAppModal/ApplicationInfoForm.tsx
@@ -19,17 +19,15 @@ import { ChangeEvent } from 'react'
 import { CustomInput, TagsContainer, Textarea } from '@devtron-labs/devtron-fe-common-lib'
 
 import { ReactComponent as ICCaretLeftSmall } from '@Icons/ic-caret-left-small.svg'
-import { ReactComponent as ICDevtronApp } from '@Icons/ic-devtron-app.svg'
 import { importComponentFromFELibrary } from '@Components/common'
 import { APP_TYPE } from '@Config/constants'
+import { getAppIconWithBackground } from '@Config/utils'
 
-import AppToCloneSelector from './AppToCloneSelector'
 import ProjectSelector from './ProjectSelector'
 import {
     ApplicationInfoFormProps,
     CreateAppFormStateActionType,
     CreateAppFormStateType,
-    CreationMethodType,
     HandleFormStateChangeParamsType,
     ProjectSelectorProps,
 } from './types'
@@ -71,17 +69,12 @@ const ApplicationInfoForm = ({
         })
     }
 
-    const handleCloneIdChange = (cloneId) => {
-        handleFormStateChange({
-            action: CreateAppFormStateActionType.updateCloneAppId,
-            value: cloneId,
-        })
-    }
+    const isMandatoryTag = formState.tags.some((tag) => tag.data.tagKey.required)
 
     return (
         // key is required for ensuring autoFocus on name on creation method change
         <div className="flexbox-col dc__gap-16 p-20 br-8 border__secondary bg__primary" key={selectedCreationMethod}>
-            <ICDevtronApp className="icon-dim-48 dc__no-shrink" />
+            {getAppIconWithBackground(isJobView ? APP_TYPE.JOB : APP_TYPE.DEVTRON_APPS, 48)}
             <div className="flexbox dc__gap-8">
                 <ProjectSelector
                     selectedProjectId={formState.projectId}
@@ -122,7 +115,9 @@ const ApplicationInfoForm = ({
                     <ICCaretLeftSmall
                         className={`scn-7 dc__no-shrink dc__transition--transform ${isTagsAccordionExpanded ? 'dc__flip-270' : 'dc__flip-180'}`}
                     />
-                    <span className="fs-13 fw-6 lh-20 cn-9">Add tags to {isJobView ? 'job' : 'application'}</span>
+                    <span className={`fs-13 fw-6 lh-20 cn-9 ${isMandatoryTag ? 'dc__required-field' : ''}`}>
+                        Add tags to {isJobView ? 'job' : 'application'}
+                    </span>
                 </button>
                 <div className={!isTagsAccordionExpanded ? 'dc__hide-section' : ''}>
                     {MandatoryTagsContainer ? (
@@ -147,13 +142,6 @@ const ApplicationInfoForm = ({
                     )}
                 </div>
             </div>
-            {selectedCreationMethod === CreationMethodType.clone && (
-                <AppToCloneSelector
-                    error={formErrorState.cloneAppId}
-                    isJobView={isJobView}
-                    handleCloneIdChange={handleCloneIdChange}
-                />
-            )}
         </div>
     )
 }
diff --git a/src/Pages/App/CreateAppModal/CloneApplicationSelectionList.tsx b/src/Pages/App/CreateAppModal/CloneApplicationSelectionList.tsx
new file mode 100644
index 0000000000..b8ab09ddd4
--- /dev/null
+++ b/src/Pages/App/CreateAppModal/CloneApplicationSelectionList.tsx
@@ -0,0 +1,169 @@
+import {
+    BaseAppMetaData,
+    Button,
+    ButtonStyleType,
+    ButtonVariantType,
+    ComponentSizeType,
+    Icon,
+    Progressing,
+} from '@devtron-labs/devtron-fe-common-lib'
+
+import { importComponentFromFELibrary } from '@Components/common'
+import { APP_TYPE } from '@Config/constants'
+import { getAppIconWithBackground } from '@Config/utils'
+
+import { AppCloneList } from './AppClone'
+import ApplicationInfoForm from './ApplicationInfoForm'
+import {
+    ApplicationSelectionListProps,
+    CreateAppFormStateActionType,
+    CreateAppFormStateType,
+    CreationMethodType,
+} from './types'
+import UpdateTemplateConfig from './UpdateTemplateConfig'
+
+const TemplateList = importComponentFromFELibrary('TemplateList', null, 'function')
+
+export const CloneApplicationSelectionList = ({
+    formState,
+    selectedCreationMethod,
+    isJobView,
+    handleFormStateChange,
+    formErrorState,
+    handleTagErrorChange,
+    isTagsAccordionExpanded,
+    toggleIsTagsAccordionExpanded,
+    handleCreationMethodChange,
+}: ApplicationSelectionListProps) => {
+    const isCreationMethodTemplate = selectedCreationMethod === CreationMethodType.template
+
+    const handleGoBack = () => {
+        handleFormStateChange({
+            action: isCreationMethodTemplate
+                ? CreateAppFormStateActionType.updateTemplateConfig
+                : CreateAppFormStateActionType.updateCloneAppConfig,
+            value: null,
+        })
+    }
+    const handleTemplateClick = ({ id, templateId, name }: CreateAppFormStateType['templateConfig']) => {
+        handleFormStateChange({
+            action: CreateAppFormStateActionType.updateTemplateConfig,
+            value: { id, templateId, name },
+        })
+    }
+
+    const handleCloneAppClick = ({ appId, appName }: BaseAppMetaData) => {
+        handleFormStateChange({
+            action: CreateAppFormStateActionType.updateCloneAppConfig,
+            value: { appId, appName },
+        })
+    }
+
+    const renderSelectionList = () => {
+        switch (selectedCreationMethod) {
+            case CreationMethodType.template:
+                return (
+                    <TemplateList
+                        handleTemplateClick={handleTemplateClick}
+                        isJobView={isJobView}
+                        isCreationMethodTemplate={isCreationMethodTemplate}
+                    />
+                )
+            case CreationMethodType.clone:
+                return (
+                    <AppCloneList
+                        handleCloneAppClick={handleCloneAppClick}
+                        isJobView={isJobView}
+                        handleCreationMethodChange={handleCreationMethodChange}
+                    />
+                )
+            default:
+                return null
+        }
+    }
+
+    const getBreadcrumbText = () => {
+        if (isCreationMethodTemplate) {
+            return 'Templates'
+        }
+
+        if (isJobView) {
+            return 'Clone Job'
+        }
+
+        return 'Clone Application'
+    }
+
+    const renderAppInfoForm = () => {
+        const breadcrumbText = getBreadcrumbText()
+        const breadcrumbDataTestId = isCreationMethodTemplate ? 'template-list-breadcrumb' : 'clone-list-breadcrumb'
+        const icon = isCreationMethodTemplate ? (
+            <Icon name="ic-app-template" color={null} />
+        ) : (
+            getAppIconWithBackground(isJobView ? APP_TYPE.JOB : APP_TYPE.DEVTRON_APPS)
+        )
+        const name = isCreationMethodTemplate ? formState.templateConfig.name : formState.cloneAppConfig.appName
+
+        return (
+            <>
+                <div className="flex left dc__gap-12 py-12 px-20">
+                    <Button
+                        icon={<Icon name="ic-caret-left" color={null} />}
+                        dataTestId={
+                            isCreationMethodTemplate
+                                ? 'create-app-modal-go-back-to-templates-list'
+                                : 'create-app-modal-go-back-to-clone-app-list'
+                        }
+                        ariaLabel={isCreationMethodTemplate ? 'go-back-to-templates-list' : 'go-back-to-clone-app-list'}
+                        variant={ButtonVariantType.secondary}
+                        style={ButtonStyleType.neutral}
+                        size={ComponentSizeType.xs}
+                        showAriaLabelInTippy={false}
+                        onClick={handleGoBack}
+                    />
+                    <div className="flex left dc__gap-6">
+                        <Button
+                            dataTestId={breadcrumbDataTestId}
+                            variant={ButtonVariantType.text}
+                            text={breadcrumbText}
+                            onClick={handleGoBack}
+                        />
+                        <span className="fs-13">/</span>
+                        <p className="m-0 flex left dc__gap-6">
+                            {icon}
+                            <span className="fs-13 lh-20 fw-6 cn-9 dc__truncate">{name}</span>
+                        </p>
+                    </div>
+                </div>
+                <div className="divider__secondary--horizontal" />
+                <div className="flexbox-col flex-grow-1 dc__overflow-auto create-app-modal__template">
+                    <div className="create-app-modal__template__loader">
+                        <Progressing size={32} />
+                    </div>
+                    <div className="create-app-modal__template__content flexbox-col dc__gap-20 flex-grow-1 bg__secondary dc__overflow-auto p-20">
+                        <ApplicationInfoForm
+                            formState={formState}
+                            handleFormStateChange={handleFormStateChange}
+                            formErrorState={formErrorState}
+                            handleTagErrorChange={handleTagErrorChange}
+                            isJobView={isJobView}
+                            selectedCreationMethod={selectedCreationMethod}
+                            isTagsAccordionExpanded={isTagsAccordionExpanded}
+                            toggleIsTagsAccordionExpanded={toggleIsTagsAccordionExpanded}
+                        />
+                        {selectedCreationMethod === CreationMethodType.template && (
+                            <UpdateTemplateConfig
+                                formState={formState}
+                                isJobView={isJobView}
+                                handleFormStateChange={handleFormStateChange}
+                                formErrorState={formErrorState}
+                            />
+                        )}
+                    </div>
+                </div>
+            </>
+        )
+    }
+
+    return !formState.cloneAppConfig && !formState.templateConfig ? renderSelectionList() : renderAppInfoForm()
+}
diff --git a/src/Pages/App/CreateAppModal/CreateAppModal.component.tsx b/src/Pages/App/CreateAppModal/CreateAppModal.component.tsx
index 51b56c057a..75db60d81a 100644
--- a/src/Pages/App/CreateAppModal/CreateAppModal.component.tsx
+++ b/src/Pages/App/CreateAppModal/CreateAppModal.component.tsx
@@ -19,21 +19,14 @@ import { useHistory } from 'react-router-dom'
 
 import {
     Button,
-    ButtonStyleType,
-    ButtonVariantType,
-    ComponentSizeType,
     Drawer,
-    Progressing,
     showError,
     ToastManager,
     ToastVariantType,
-    validateDescription,
     validateTagKeyValue,
     validateTagValue,
 } from '@devtron-labs/devtron-fe-common-lib'
 
-import { ReactComponent as ICAppTemplate } from '@Icons/ic-app-template.svg'
-import { ReactComponent as ICBack } from '@Icons/ic-caret-left-small.svg'
 import { importComponentFromFELibrary } from '@Components/common'
 import { saveHostURLConfiguration } from '@Components/hostURL/hosturl.service'
 import { createJob } from '@Components/Jobs/Service'
@@ -42,6 +35,7 @@ import { APP_COMPOSE_STAGE, getAppComposeURL, URLS } from '@Config/routes'
 import { getHostURLConfiguration } from '@Services/service'
 
 import ApplicationInfoForm from './ApplicationInfoForm'
+import { CloneApplicationSelectionList } from './CloneApplicationSelectionList'
 import { createAppInitialFormErrorState, createAppInitialFormState } from './constants'
 import HeaderSection from './HeaderSection'
 import { createApp } from './service'
@@ -54,12 +48,10 @@ import {
     CreateAppModalProps,
     CreationMethodType,
 } from './types'
-import UpdateTemplateConfig from './UpdateTemplateConfig'
-import { getCreateMethodConfig, validateAppName, validateCloneApp, validateProject } from './utils'
+import { getCreateMethodConfig, getNoItemSelectToastText, validateFormField } from './utils'
 
 import './styles.scss'
 
-const TemplateList = importComponentFromFELibrary('TemplateList', null, 'function')
 const createDevtronAppUsingTemplate = importComponentFromFELibrary('createDevtronAppUsingTemplate', null, 'function')
 
 const CreateAppModal = ({ isJobView, handleClose }: CreateAppModalProps) => {
@@ -87,28 +79,12 @@ const CreateAppModal = ({ isJobView, handleClose }: CreateAppModalProps) => {
         setIsTagsAccordionExpanded((prev) => !prev)
     }
 
-    const validateFormField = (field: keyof CreateAppFormStateType, value) => {
-        switch (field) {
-            case 'name':
-                return validateAppName(value).message
-            case 'description':
-                return validateDescription(value).message
-            case 'projectId':
-                return validateProject(value).message
-            case 'cloneAppId':
-                return selectedCreationMethod === CreationMethodType.clone ? validateCloneApp(value).message : null
-            default:
-                throw new Error(`Invalid field: ${field}`)
-        }
-    }
-
     const validateForm = () => {
         const updatedFormErrorState = structuredClone(formErrorState)
 
         updatedFormErrorState.projectId = validateFormField('projectId', formState.projectId)
         updatedFormErrorState.name = validateFormField('name', formState.name)
         updatedFormErrorState.description = validateFormField('description', formState.description)
-        updatedFormErrorState.cloneAppId = validateFormField('cloneAppId', formState.cloneAppId)
 
         const labelTags = []
         updatedFormErrorState.tags = {}
@@ -189,9 +165,8 @@ const CreateAppModal = ({ isJobView, handleClose }: CreateAppModalProps) => {
                     case CreateAppFormStateActionType.updateTags:
                         updatedFormState.tags = value
                         break
-                    case CreateAppFormStateActionType.updateCloneAppId:
-                        updatedFormState.cloneAppId = value
-                        updatedFormErrorState.cloneAppId = validateFormField('cloneAppId', value)
+                    case CreateAppFormStateActionType.updateCloneAppConfig:
+                        updatedFormState.cloneAppConfig = value
                         break
                     case CreateAppFormStateActionType.updateGitMaterials:
                         updatedFormState.gitMaterials = value.data
@@ -240,19 +215,6 @@ const CreateAppModal = ({ isJobView, handleClose }: CreateAppModalProps) => {
         }))
     }
 
-    const handleTemplateClick = ({ id, templateId, name }: CreateAppFormStateType['templateConfig']) => {
-        handleFormStateChange({
-            action: CreateAppFormStateActionType.updateTemplateConfig,
-            value: { id, templateId, name },
-        })
-    }
-
-    const goBackToTemplatesList = () =>
-        handleFormStateChange({
-            action: CreateAppFormStateActionType.updateTemplateConfig,
-            value: null,
-        })
-
     const getHostURLConfig = async () => {
         try {
             const { result } = await getHostURLConfiguration()
@@ -292,7 +254,7 @@ const CreateAppModal = ({ isJobView, handleClose }: CreateAppModalProps) => {
             if (!formState.templateConfig?.templateId) {
                 ToastManager.showToast({
                     variant: ToastVariantType.error,
-                    description: 'Please select a template to create app',
+                    description: getNoItemSelectToastText(CreationMethodType.template),
                 })
                 return
             }
@@ -306,6 +268,13 @@ const CreateAppModal = ({ isJobView, handleClose }: CreateAppModalProps) => {
             }
         }
 
+        if (selectedCreationMethod === CreationMethodType.clone && !formState.cloneAppConfig?.appId) {
+            ToastManager.showToast({
+                variant: ToastVariantType.error,
+                description: getNoItemSelectToastText(CreationMethodType.clone),
+            })
+        }
+
         if (!isFormValid || invalidLabels) {
             ToastManager.showToast({
                 variant: ToastVariantType.error,
@@ -325,7 +294,7 @@ const CreateAppModal = ({ isJobView, handleClose }: CreateAppModalProps) => {
             appType: isJobView ? 2 : null,
             ...(selectedCreationMethod === CreationMethodType.clone
                 ? {
-                      templateId: formState.cloneAppId,
+                      templateId: formState.cloneAppConfig.appId,
                   }
                 : null),
             ...(isCreationMethodTemplate
@@ -358,6 +327,52 @@ const CreateAppModal = ({ isJobView, handleClose }: CreateAppModalProps) => {
         }
     }
 
+    const handleCreationMethodChange = (method: CreationMethodType) => {
+        handleFormStateChange({
+            action: isCreationMethodTemplate
+                ? CreateAppFormStateActionType.updateTemplateConfig
+                : CreateAppFormStateActionType.updateCloneAppConfig,
+            value: null,
+        })
+
+        setSelectedCreationMethod(method)
+    }
+
+    const getSelectedMethodContent = () => {
+        switch (selectedCreationMethod) {
+            case CreationMethodType.blank:
+                return (
+                    <ApplicationInfoForm
+                        formState={formState}
+                        handleFormStateChange={handleFormStateChange}
+                        formErrorState={formErrorState}
+                        handleTagErrorChange={handleTagErrorChange}
+                        isJobView={isJobView}
+                        selectedCreationMethod={selectedCreationMethod}
+                        isTagsAccordionExpanded={isTagsAccordionExpanded}
+                        toggleIsTagsAccordionExpanded={toggleIsTagsAccordionExpanded}
+                    />
+                )
+            case CreationMethodType.clone:
+            case CreationMethodType.template:
+                return (
+                    <CloneApplicationSelectionList
+                        formState={formState}
+                        formErrorState={formErrorState}
+                        selectedCreationMethod={selectedCreationMethod}
+                        handleFormStateChange={handleFormStateChange}
+                        handleTagErrorChange={handleTagErrorChange}
+                        isJobView={isJobView}
+                        isTagsAccordionExpanded={isTagsAccordionExpanded}
+                        toggleIsTagsAccordionExpanded={toggleIsTagsAccordionExpanded}
+                        handleCreationMethodChange={handleCreationMethodChange}
+                    />
+                )
+            default:
+                return null
+        }
+    }
+
     return (
         <Drawer position="right" width="1024px" onEscape={handleClose}>
             <div className="h-100 bg__modal--primary flexbox-col dc__overflow-hidden">
@@ -365,85 +380,15 @@ const CreateAppModal = ({ isJobView, handleClose }: CreateAppModalProps) => {
                 <div className="flexbox flex-grow-1 dc__overflow-hidden">
                     <Sidebar
                         selectedCreationMethod={selectedCreationMethod}
-                        handleCreationMethodChange={setSelectedCreationMethod}
+                        handleCreationMethodChange={handleCreationMethodChange}
                         createMethodConfig={createMethodConfig}
                         isJobView={isJobView}
                     />
-                    {selectedCreationMethod !== CreationMethodType.template && (
-                        <div className="p-20 flexbox-col dc__gap-20 flex-grow-1 bg__secondary dc__overflow-auto">
-                            <ApplicationInfoForm
-                                formState={formState}
-                                handleFormStateChange={handleFormStateChange}
-                                formErrorState={formErrorState}
-                                handleTagErrorChange={handleTagErrorChange}
-                                isJobView={isJobView}
-                                selectedCreationMethod={selectedCreationMethod}
-                                isTagsAccordionExpanded={isTagsAccordionExpanded}
-                                toggleIsTagsAccordionExpanded={toggleIsTagsAccordionExpanded}
-                            />
-                        </div>
-                    )}
-                    {isCreationMethodTemplate && (
-                        <div className="flexbox-col flex-grow-1 bg__secondary dc__overflow-auto">
-                            {formState.templateConfig ? (
-                                <>
-                                    <div className="flex left dc__gap-12 py-12 px-20">
-                                        <Button
-                                            icon={<ICBack />}
-                                            dataTestId="create-app-modal-go-back-to-templates-list"
-                                            ariaLabel="go-back-to-templates-list"
-                                            variant={ButtonVariantType.secondary}
-                                            style={ButtonStyleType.neutral}
-                                            size={ComponentSizeType.xs}
-                                            showAriaLabelInTippy={false}
-                                            onClick={goBackToTemplatesList}
-                                        />
-                                        <div className="flex left dc__gap-4">
-                                            <Button
-                                                dataTestId="template-list-breadcrumb"
-                                                variant={ButtonVariantType.text}
-                                                text="Templates"
-                                                onClick={goBackToTemplatesList}
-                                            />
-                                            <span>/</span>
-                                            <p className="m-0 flex left dc__gap-6">
-                                                <ICAppTemplate className="icon-dim-20 p-1 dc__no-shrink" />
-                                                <span className="fs-13 lh-20 fw-6 cn-9 dc__truncate">
-                                                    {formState.templateConfig.name}
-                                                </span>
-                                            </p>
-                                        </div>
-                                    </div>
-                                    <div className="divider__secondary--horizontal" />
-                                    <div className="flexbox-col flex-grow-1 dc__overflow-auto create-app-modal__template">
-                                        <div className="create-app-modal__template__loader">
-                                            <Progressing size={32} />
-                                        </div>
-                                        <div className="create-app-modal__template__content flexbox-col dc__gap-20 flex-grow-1 bg__secondary dc__overflow-auto p-20">
-                                            <ApplicationInfoForm
-                                                formState={formState}
-                                                handleFormStateChange={handleFormStateChange}
-                                                formErrorState={formErrorState}
-                                                handleTagErrorChange={handleTagErrorChange}
-                                                isJobView={isJobView}
-                                                selectedCreationMethod={selectedCreationMethod}
-                                                isTagsAccordionExpanded={isTagsAccordionExpanded}
-                                                toggleIsTagsAccordionExpanded={toggleIsTagsAccordionExpanded}
-                                            />
-                                            <UpdateTemplateConfig
-                                                formState={formState}
-                                                isJobView={isJobView}
-                                                handleFormStateChange={handleFormStateChange}
-                                                formErrorState={formErrorState}
-                                            />
-                                        </div>
-                                    </div>
-                                </>
-                            ) : (
-                                TemplateList && <TemplateList handleTemplateClick={handleTemplateClick} />
-                            )}
-                        </div>
-                    )}
+                    <div
+                        className={`flexbox-col flex-grow-1 bg__secondary dc__overflow-auto ${selectedCreationMethod === CreationMethodType.blank ? 'p-20' : ''}`}
+                    >
+                        {getSelectedMethodContent()}
+                    </div>
                 </div>
                 <div className="px-20 py-16 flexbox dc__content-end dc__no-shrink border__primary--top">
                     <Button
diff --git a/src/Pages/App/CreateAppModal/HeaderSection.tsx b/src/Pages/App/CreateAppModal/HeaderSection.tsx
index 81449efed5..08783c8ae6 100644
--- a/src/Pages/App/CreateAppModal/HeaderSection.tsx
+++ b/src/Pages/App/CreateAppModal/HeaderSection.tsx
@@ -22,7 +22,7 @@ import { HeaderSectionProps } from './types'
 
 const HeaderSection = ({ isJobView, handleClose, isCloseDisabled }: HeaderSectionProps) => (
     <div className="flex flex-align-center flex-justify border__primary--bottom py-12 px-20">
-        <h2 className="fs-16 fw-6 lh-1-43 m-0">Create {isJobView ? 'Job' : 'Devtron Application'}</h2>
+        <h2 className="fs-16 fw-6 lh-1-43 m-0 cn-9">Create {isJobView ? 'Job' : 'Devtron Application'}</h2>
         <Button
             onClick={handleClose}
             dataTestId={`close-create-custom${isJobView ? 'job' : 'app'}-wing`}
diff --git a/src/Pages/App/CreateAppModal/Sidebar.tsx b/src/Pages/App/CreateAppModal/Sidebar.tsx
index 7d1cf69c09..275c5ddedb 100644
--- a/src/Pages/App/CreateAppModal/Sidebar.tsx
+++ b/src/Pages/App/CreateAppModal/Sidebar.tsx
@@ -30,6 +30,31 @@ const Sidebar = ({
         handleCreationMethodChange(creationMethod)
     }
 
+    const renderAppContent = () => (
+        <>
+            <p className="m-0">In Devtron, an &quot;Application&quot; represents your software project or service.</p>
+            <p className="m-0">
+                It serves as a container for your deployment configurations, environments, and other settings. Define
+                your application to start managing and monitoring its deployment efficiently.
+            </p>
+            <p className="m-0">
+                Applications are not environment specific and can be deployed to multiple environments.
+            </p>
+        </>
+    )
+
+    const renderJobContent = () => (
+        <>
+            <p className="m-0">Job allows manual and automated execution of your source code.</p>
+            <p className="m-0">
+                Job pipelines do not have a deployment stage as the job is limited to your source code only.
+            </p>
+            <p className="m-0">
+                You can execute custom tasks or leverage the plugin library to execute tasks in a job pipeline.
+            </p>
+        </>
+    )
+
     return (
         <div className="w-250 p-20 flexbox-col dc__gap-24 dc__no-shrink dc__overflow-auto">
             <div className="flexbox-col">
@@ -52,30 +77,14 @@ const Sidebar = ({
                     )
                 })}
             </div>
-            {!isJobView && (
-                <>
-                    <div className="divider__secondary--horizontal" />
-                    <ModalSidebarPanel
-                        heading={null}
-                        documentationLink={DOCUMENTATION.APP_CREATE}
-                        rootClassName="w-100 dc__no-background-imp"
-                    >
-                        <div className="flexbox-col dc__gap-24">
-                            <p className="m-0">
-                                In Devtron, an &quot;Application&quot; represents your software project or service.
-                            </p>
-                            <p className="m-0">
-                                It serves as a container for your deployment configurations, environments, and other
-                                settings. Define your application to start managing and monitoring its deployment
-                                efficiently.
-                            </p>
-                            <p className="m-0">
-                                Applications are not environment specific and can be deployed to multiple environments.
-                            </p>
-                        </div>
-                    </ModalSidebarPanel>
-                </>
-            )}
+            <div className="divider__secondary--horizontal" />
+            <ModalSidebarPanel
+                heading={null}
+                documentationLink={isJobView ? DOCUMENTATION.JOBS : DOCUMENTATION.APP_CREATE}
+                rootClassName="w-100 dc__no-background-imp"
+            >
+                <div className="flexbox-col dc__gap-24">{isJobView ? renderJobContent() : renderAppContent()}</div>
+            </ModalSidebarPanel>
         </div>
     )
 }
diff --git a/src/Pages/App/CreateAppModal/constants.ts b/src/Pages/App/CreateAppModal/constants.ts
index 0396d0c3ed..423ad6bbdc 100644
--- a/src/Pages/App/CreateAppModal/constants.ts
+++ b/src/Pages/App/CreateAppModal/constants.ts
@@ -28,6 +28,7 @@ export const createAppInitialFormState: CreateAppFormStateType = {
     gitMaterials: null,
     buildConfiguration: null,
     workflowConfig: null,
+    cloneAppConfig: null,
 }
 
 export const createAppInitialFormErrorState: CreateAppFormErrorStateType = {
@@ -35,7 +36,6 @@ export const createAppInitialFormErrorState: CreateAppFormErrorStateType = {
     projectId: '',
     description: '',
     tags: {},
-    cloneAppId: null,
     gitMaterials: null,
     workflowConfig: null,
 }
diff --git a/src/Pages/App/CreateAppModal/service.ts b/src/Pages/App/CreateAppModal/service.ts
index 61ce62c2af..486ab54271 100644
--- a/src/Pages/App/CreateAppModal/service.ts
+++ b/src/Pages/App/CreateAppModal/service.ts
@@ -14,8 +14,69 @@
  * limitations under the License.
  */
 
-import { post } from '@devtron-labs/devtron-fe-common-lib'
+import { abortPreviousRequests, post } from '@devtron-labs/devtron-fe-common-lib'
 
-import { Routes } from '@Config/constants'
+import { getJobs } from '@Components/Jobs/Service'
+import { APP_TYPE, Routes } from '@Config/constants'
+import { getAppIconWithBackground } from '@Config/utils'
+import { getAppListMin } from '@Services/service'
+
+import { CloneListResponse, CloneListTypes } from './AppClone/types'
 
 export const createApp = (request) => post(Routes.APP, request)
+
+export const fetchDevtronCloneList = async ({
+    offset = 0,
+    isJobView = false,
+    searchKey = '',
+    cloneListAbortControllerRef,
+    handleCloneAppClick,
+}: CloneListTypes): Promise<CloneListResponse> =>
+    abortPreviousRequests(async () => {
+        if (isJobView) {
+            const res = await getJobs({
+                teams: [],
+                appStatuses: [],
+                appNameSearch: '',
+                offset,
+                size: 20,
+                sortBy: 'appNameSort',
+                sortOrder: 'ASC',
+                searchKey,
+            })
+
+            const jobContainers = res.result?.jobContainers ?? []
+            const totalCount = res.result?.jobCount ?? 0
+
+            const list = jobContainers.map((job) => ({
+                id: String(job.jobId),
+                title: job.jobName,
+                description: job.description.description,
+                author: job.description.createdBy,
+                Icon: getAppIconWithBackground(APP_TYPE.JOB, 40),
+                onClick: () => handleCloneAppClick({ appId: job.jobId, appName: job.jobName }),
+            }))
+
+            return { type: APP_TYPE.JOB, list, totalCount }
+        }
+        const res = await getAppListMin(
+            null,
+            { signal: cloneListAbortControllerRef.current.signal },
+            searchKey,
+            isJobView,
+            offset,
+        )
+
+        const apps = res.result ?? []
+
+        const list = apps.map((app) => ({
+            id: String(app.id),
+            title: app.name,
+            description: app.description,
+            author: app.createdBy,
+            Icon: getAppIconWithBackground(APP_TYPE.DEVTRON_APPS, 40),
+            onClick: () => handleCloneAppClick({ appId: app.id, appName: app.name }),
+        }))
+
+        return { type: APP_TYPE.DEVTRON_APPS, list, totalCount: apps.length }
+    }, cloneListAbortControllerRef)
diff --git a/src/Pages/App/CreateAppModal/types.ts b/src/Pages/App/CreateAppModal/types.ts
index cb1c0db04a..7dff59f886 100644
--- a/src/Pages/App/CreateAppModal/types.ts
+++ b/src/Pages/App/CreateAppModal/types.ts
@@ -17,6 +17,7 @@
 import { SyntheticEvent } from 'react'
 
 import {
+    BaseAppMetaData,
     ButtonProps,
     DynamicDataTableCellErrorType,
     DynamicDataTableRowType,
@@ -56,6 +57,7 @@ export interface CreateAppFormStateType {
     gitMaterials: CreateAppGitMaterialType[]
     buildConfiguration: Required<Pick<CIConfigProps['parentState']['ciConfig'], 'dockerRegistry' | 'dockerRepository'>>
     workflowConfig: CreateAppWorkflowConfigType
+    cloneAppConfig: BaseAppMetaData
 }
 
 export interface CreateAppFormErrorStateType {
@@ -63,7 +65,6 @@ export interface CreateAppFormErrorStateType {
     name: string
     description: string
     tags: DynamicDataTableCellErrorType<TagsTableColumnsType>
-    cloneAppId: string | null
     gitMaterials: boolean
     // Map of workflow id to error message
     workflowConfig: Record<string, string>
@@ -85,6 +86,7 @@ export enum CreateAppFormStateActionType {
     updateBuildConfiguration = 'updateBuildConfiguration',
     updateWorkflowConfig = 'updateWorkflowConfig',
     updateTemplateConfig = 'updateTemplateConfig',
+    updateCloneAppConfig = 'updateCloneAppConfig',
 }
 
 type BaseHandleFormStateChangeParamsType<Action extends CreateAppFormStateActionType, Value> = {
@@ -129,6 +131,10 @@ export type HandleFormStateChangeParamsType =
           CreateAppFormStateActionType.updateTemplateConfig,
           CreateAppFormStateType['templateConfig']
       >
+    | BaseHandleFormStateChangeParamsType<
+          CreateAppFormStateActionType.updateCloneAppConfig,
+          CreateAppFormStateType['cloneAppConfig']
+      >
 
 export interface CreateAppModalProps {
     isJobView: boolean
@@ -160,15 +166,23 @@ export interface SidebarProps extends Pick<CreateAppModalProps, 'isJobView'> {
     createMethodConfig: ReturnType<typeof getCreateMethodConfig>
 }
 
-export interface AppToCloneSelectorProps
-    extends Pick<CreateAppModalProps, 'isJobView'>,
-        Required<Pick<SelectPickerProps, 'error'>> {
-    handleCloneIdChange: (cloneAppId: CreateAppFormStateType['cloneAppId']) => void
-}
-
 export interface UpdateTemplateConfigProps
     extends Pick<CreateAppModalProps, 'isJobView'>,
         Pick<ApplicationInfoFormProps, 'handleFormStateChange'> {
     formState: CreateAppFormStateType
     formErrorState: CreateAppFormErrorStateType
 }
+
+export interface ApplicationSelectionListProps
+    extends Pick<CreateAppModalProps, 'isJobView'>,
+        Pick<
+            ApplicationInfoFormProps,
+            | 'formState'
+            | 'selectedCreationMethod'
+            | 'isTagsAccordionExpanded'
+            | 'toggleIsTagsAccordionExpanded'
+            | 'handleFormStateChange'
+            | 'formErrorState'
+            | 'handleTagErrorChange'
+        >,
+        Pick<SidebarProps, 'handleCreationMethodChange'> {}
diff --git a/src/Pages/App/CreateAppModal/utils.tsx b/src/Pages/App/CreateAppModal/utils.tsx
index d03620d569..1d6f7faf6f 100644
--- a/src/Pages/App/CreateAppModal/utils.tsx
+++ b/src/Pages/App/CreateAppModal/utils.tsx
@@ -14,7 +14,13 @@
  * limitations under the License.
  */
 
-import { Icon, IconsProps, SelectPickerOptionType, ValidationResponseType } from '@devtron-labs/devtron-fe-common-lib'
+import {
+    Icon,
+    IconsProps,
+    SelectPickerOptionType,
+    validateDescription,
+    ValidationResponseType,
+} from '@devtron-labs/devtron-fe-common-lib'
 
 import { importComponentFromFELibrary } from '@Components/common'
 import { MAX_LENGTH_30 } from '@Config/constantMessaging'
@@ -60,14 +66,6 @@ export const validateProject = (projectId: CreateAppFormStateType['projectId']):
     return { isValid: false, message: 'Please select a project' }
 }
 
-export const validateCloneApp = (cloneAppId: CreateAppFormStateType['cloneAppId']): ValidationResponseType => {
-    if (cloneAppId) {
-        return { isValid: true, message: '' }
-    }
-
-    return { isValid: false, message: 'Please select an application to clone' }
-}
-
 export const getCreateMethodConfig = (
     isJobView: CreateAppModalProps['isJobView'],
     selectedCreationMethod: CreationMethodType,
@@ -78,7 +76,7 @@ export const getCreateMethodConfig = (
 
     return [
         {
-            label: `Blank ${labelSuffix}`,
+            label: 'Create from Scratch',
             value: CreationMethodType.blank,
             startIcon: (
                 <Icon
@@ -117,3 +115,28 @@ export const getCreateMethodConfig = (
               ]),
     ]
 }
+
+export const getNoItemSelectToastText = (selectedCreationMethod: CreationMethodType) => {
+    if (selectedCreationMethod === CreationMethodType.template) {
+        return 'Please select a template to create app'
+    }
+
+    if (selectedCreationMethod === CreationMethodType.clone) {
+        return 'Please select an app to clone'
+    }
+
+    return null
+}
+
+export const validateFormField = (field: keyof CreateAppFormStateType, value) => {
+    switch (field) {
+        case 'name':
+            return validateAppName(value).message
+        case 'description':
+            return validateDescription(value).message
+        case 'projectId':
+            return validateProject(value).message
+        default:
+            throw new Error(`Invalid field: ${field}`)
+    }
+}
diff --git a/src/Pages/GlobalConfigurations/Authorization/PermissionGroups/List/NoPermissionGroups.tsx b/src/Pages/GlobalConfigurations/Authorization/PermissionGroups/List/NoPermissionGroups.tsx
index 7676640262..73e804dfa4 100644
--- a/src/Pages/GlobalConfigurations/Authorization/PermissionGroups/List/NoPermissionGroups.tsx
+++ b/src/Pages/GlobalConfigurations/Authorization/PermissionGroups/List/NoPermissionGroups.tsx
@@ -16,8 +16,9 @@
 
 import { Button, ButtonComponentType, ComponentSizeType, GenericEmptyState } from '@devtron-labs/devtron-fe-common-lib'
 
+import nullStateImage from '@Images/empty-list.png'
+
 import { ReactComponent as AddIcon } from '../../../../../assets/icons/ic-add.svg'
-import nullStateImage from '../../../../../assets/img/empty-applist@2x.png'
 import { URLS } from '../../../../../config'
 import { EMPTY_STATE_STATUS } from '../../../../../config/constantMessaging'
 
diff --git a/src/Pages/GlobalConfigurations/Authorization/UserPermissions/List/NoUsers.tsx b/src/Pages/GlobalConfigurations/Authorization/UserPermissions/List/NoUsers.tsx
index 42289ed3c6..5733221e11 100644
--- a/src/Pages/GlobalConfigurations/Authorization/UserPermissions/List/NoUsers.tsx
+++ b/src/Pages/GlobalConfigurations/Authorization/UserPermissions/List/NoUsers.tsx
@@ -16,8 +16,9 @@
 
 import { Button, ButtonComponentType, ComponentSizeType, GenericEmptyState } from '@devtron-labs/devtron-fe-common-lib'
 
+import nullStateImage from '@Images/empty-list.png'
+
 import { ReactComponent as AddIcon } from '../../../../../assets/icons/ic-add.svg'
-import nullStateImage from '../../../../../assets/img/empty-applist@2x.png'
 import { URLS } from '../../../../../config'
 import { EMPTY_STATE_STATUS } from '../../../../../config/constantMessaging'
 
diff --git a/src/Pages/GlobalConfigurations/Authorization/UserPermissions/SSONotConfiguredState.tsx b/src/Pages/GlobalConfigurations/Authorization/UserPermissions/SSONotConfiguredState.tsx
index 221e605702..722cab2497 100644
--- a/src/Pages/GlobalConfigurations/Authorization/UserPermissions/SSONotConfiguredState.tsx
+++ b/src/Pages/GlobalConfigurations/Authorization/UserPermissions/SSONotConfiguredState.tsx
@@ -18,7 +18,8 @@ import { Link } from 'react-router-dom'
 
 import { GenericEmptyState, InfoBlock } from '@devtron-labs/devtron-fe-common-lib'
 
-import EmptyImage from '../../../../assets/img/empty-applist@2x.png'
+import EmptyImage from '@Images/empty-list.png'
+
 import { SSO_NOT_CONFIGURED_STATE_TEXTS } from '../../../../config/constantMessaging'
 
 const renderSsoInfoDescription = () => (
diff --git a/src/Pages/GlobalConfigurations/ClustersAndEnvironments/CreateCluster/types.ts b/src/Pages/GlobalConfigurations/ClustersAndEnvironments/CreateCluster/types.ts
index e856a96219..604505b6a7 100644
--- a/src/Pages/GlobalConfigurations/ClustersAndEnvironments/CreateCluster/types.ts
+++ b/src/Pages/GlobalConfigurations/ClustersAndEnvironments/CreateCluster/types.ts
@@ -1,4 +1,4 @@
-import { IconName } from '@devtron-labs/devtron-fe-common-lib/dist'
+import { IconName } from '@devtron-labs/devtron-fe-common-lib'
 
 export enum CreateClusterTypeEnum {
     CONNECT_CLUSTER = 'connect-cluster',
diff --git a/src/assets/icons/ic-app-template.svg b/src/assets/icons/ic-app-template.svg
deleted file mode 100644
index 70a64cf7a5..0000000000
--- a/src/assets/icons/ic-app-template.svg
+++ /dev/null
@@ -1,23 +0,0 @@
-<!--
-  - Copyright (c) 2024. Devtron Inc.
-  -
-  - Licensed under the Apache License, Version 2.0 (the "License");
-  - you may not use this file except in compliance with the License.
-  - You may obtain a copy of the License at
-  -
-  -     http://www.apache.org/licenses/LICENSE-2.0
-  -
-  - Unless required by applicable law or agreed to in writing, software
-  - distributed under the License is distributed on an "AS IS" BASIS,
-  - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  - See the License for the specific language governing permissions and
-  - limitations under the License.
-  -->
-
-<svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg" vector-effect="non-scaling-effect">
-<rect width="48" height="48" rx="6" fill="#FFF8ED"/>
-<path d="M9 11.5001C9 10.1193 10.1193 9 11.5001 9H36.5007C37.8814 9 39.0007 10.1193 39.0007 11.5001V14.0001C39.0007 15.3809 37.8814 16.5002 36.5007 16.5002H11.5001C10.1193 16.5002 9 15.3809 9 14.0001V11.5001Z" fill="#FFC266"/>
-<path d="M9 21.4981C9 20.1174 10.1193 18.998 11.5001 18.998H20.2503C21.631 18.998 22.7503 20.1174 22.7503 21.4981V25.2482C22.7503 26.6289 21.631 27.7483 20.2503 27.7483H11.5001C10.1193 27.7483 9 26.6289 9 25.2482V21.4981Z" fill="#FFE5BE"/>
-<path d="M9 32.7501C9 31.3693 10.1193 30.25 11.5001 30.25H20.2503C21.631 30.25 22.7503 31.3693 22.7503 32.7501V36.5002C22.7503 37.8809 21.631 39.0002 20.2503 39.0002H11.5001C10.1193 39.0002 9 37.8809 9 36.5002V32.7501Z" fill="#FFE5BE"/>
-<path d="M25.25 21.4981C25.25 20.1174 26.3693 18.998 27.7501 18.998H36.5003C37.881 18.998 39.0003 20.1174 39.0003 21.4981V36.4985C39.0003 37.8792 37.881 38.9986 36.5003 38.9986H27.7501C26.3693 38.9986 25.25 37.8792 25.25 36.4985V21.4981Z" fill="#FFC266"/>
-</svg>
diff --git a/src/assets/img/empty-applist@2x.png b/src/assets/img/empty-list.png
similarity index 100%
rename from src/assets/img/empty-applist@2x.png
rename to src/assets/img/empty-list.png
diff --git a/src/components/Jobs/Types.ts b/src/components/Jobs/Types.ts
index 7ce0545c42..789dcf02f8 100644
--- a/src/components/Jobs/Types.ts
+++ b/src/components/Jobs/Types.ts
@@ -151,18 +151,22 @@ export interface JobsEmptyProps {
     clickHandler: () => void
 }
 
+export interface JobContainerTypes {
+    id: number
+    jobName: string
+    appName: string
+    jobId: number
+    ciPipelines: JobCIPipeline[]
+    description: {
+        description: string
+        updatedBy: string
+        createdBy: string
+    }
+    projectId: number
+}
+
 export type JobList = ResponseType<{
-    jobContainers?: {
-        id: number
-        jobName: string
-        appName: string
-        jobId: number
-        ciPipelines: JobCIPipeline[]
-        description: {
-            description: string
-        }
-        projectId: number
-    }[]
+    jobContainers?: JobContainerTypes[]
     jobCount: number
 }>
 
diff --git a/src/components/app/Overview/utils.tsx b/src/components/app/Overview/utils.tsx
index 8646e8e1ea..08860d6dcb 100644
--- a/src/components/app/Overview/utils.tsx
+++ b/src/components/app/Overview/utils.tsx
@@ -15,11 +15,10 @@
  */
 
 import { AppOverviewProps } from '../types'
-import { ReactComponent as AppIcon } from '../../../assets/icons/ic-devtron-app.svg'
-import { ReactComponent as JobIcon } from '../../../assets/icons/ic-job-node.svg'
 import { DefaultJobNote, DefaultAppNote, DefaultHelmChartNote } from '../list-new/Constants'
 import { EMPTY_STATE_STATUS } from '../../../config/constantMessaging'
-import { ResourceKindType } from '@devtron-labs/devtron-fe-common-lib'
+import { IconBaseSizeType, ResourceKindType } from '@devtron-labs/devtron-fe-common-lib'
+import { getAppIconWithBackground } from '@Config/utils'
 
 const {
     OVERVIEW: { APP_DESCRIPTION, JOB_DESCRIPTION },
@@ -36,20 +35,21 @@ export const getResourceKindFromAppType = (appType: AppOverviewProps['appType'])
     }
 }
 
-export const getAppConfig = (appType: AppOverviewProps['appType']) => {
+export const getAppConfig = (appType: AppOverviewProps['appType'], iconSize: IconBaseSizeType = 48) => {
+    const icon = getAppIconWithBackground(appType, iconSize)
     switch (appType) {
         case 'app':
             return {
                 resourceName: 'application',
                 defaultNote: DefaultAppNote,
-                icon: <AppIcon className="icon-dim-48" />,
+                icon,
                 defaultDescription: APP_DESCRIPTION,
             }
         case 'job':
             return {
                 resourceName: 'job',
                 defaultNote: DefaultJobNote,
-                icon: <JobIcon className="icon-dim-48 dc__icon-bg-color br-4 p-8" />,
+                icon,
                 defaultDescription: JOB_DESCRIPTION,
             }
         case 'helm-chart':
@@ -60,4 +60,4 @@ export const getAppConfig = (appType: AppOverviewProps['appType']) => {
                 defaultDescription: APP_DESCRIPTION,
             }
     }
-}
\ No newline at end of file
+}
diff --git a/src/config/constants.ts b/src/config/constants.ts
index cab4baa01a..433a810d7d 100644
--- a/src/config/constants.ts
+++ b/src/config/constants.ts
@@ -379,6 +379,7 @@ export const DOCUMENTATION = {
     GLOBAL_CONFIG_USER: `${DOCUMENTATION_HOME_PAGE}${DOCUMENTATION_VERSION}/getting-started/global-configurations/authorization/user-access`,
     HOME_PAGE: DOCUMENTATION_HOME_PAGE,
     HYPERION: `${DOCUMENTATION_HOME_PAGE}/#hyperion`,
+    JOBS: `${DOCUMENTATION_HOME_PAGE}${DOCUMENTATION_VERSION}/usage/jobs`,
     JOB_CRONJOB: `${DOCUMENTATION_HOME_PAGE}${DOCUMENTATION_VERSION}/usage/applications/creating-application/deployment-template/job-and-cronjob`,
     JOB_SOURCE_CODE: `${DOCUMENTATION_HOME_PAGE}${DOCUMENTATION_VERSION}/usage/jobs/configuration-job`,
     JOB_WORKFLOW_EDITOR: `${DOCUMENTATION_HOME_PAGE}${DOCUMENTATION_VERSION}/usage/jobs/workflow-editor-job`,
diff --git a/src/config/utils.ts b/src/config/utils.ts
deleted file mode 100644
index 825c2aafec..0000000000
--- a/src/config/utils.ts
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2024. Devtron Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import {
-    DEVTRON_DEFAULT_RELEASE_NAME,
-    DEVTRON_DEFAULT_NAMESPACE,
-    DEVTRON_DEFAULT_CLUSTER_ID,
-} from '.'
-
-export const checkIfDevtronOperatorHelmRelease = (
-    releaseName: string,
-    namespace: string,
-    clusterId: string,
-): boolean => {
-    return (
-        releaseName === DEVTRON_DEFAULT_RELEASE_NAME &&
-        namespace === DEVTRON_DEFAULT_NAMESPACE &&
-        clusterId === DEVTRON_DEFAULT_CLUSTER_ID
-    )
-}
diff --git a/src/config/utils.tsx b/src/config/utils.tsx
new file mode 100644
index 0000000000..71d1b308fb
--- /dev/null
+++ b/src/config/utils.tsx
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2024. Devtron Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { Icon, IconBaseSizeType } from '@devtron-labs/devtron-fe-common-lib'
+
+import { AppOverviewProps } from '@Components/app/types'
+
+import { APP_TYPE, DEVTRON_DEFAULT_CLUSTER_ID, DEVTRON_DEFAULT_NAMESPACE, DEVTRON_DEFAULT_RELEASE_NAME } from '.'
+
+export const checkIfDevtronOperatorHelmRelease = (releaseName: string, namespace: string, clusterId: string): boolean =>
+    releaseName === DEVTRON_DEFAULT_RELEASE_NAME &&
+    namespace === DEVTRON_DEFAULT_NAMESPACE &&
+    clusterId === DEVTRON_DEFAULT_CLUSTER_ID
+
+export const getAppIconWithBackground = (appType: AppOverviewProps['appType'], iconSize: IconBaseSizeType = 20) => {
+    switch (appType) {
+        case APP_TYPE.DEVTRON_APPS:
+            return <Icon name="ic-devtron-app" color={null} size={iconSize} />
+        case APP_TYPE.JOB:
+            return <Icon name="ic-devtron-job" color={null} size={iconSize} />
+        default:
+            return null
+    }
+}
diff --git a/src/services/service.ts b/src/services/service.ts
index 5faa293b23..50829c8eae 100644
--- a/src/services/service.ts
+++ b/src/services/service.ts
@@ -147,6 +147,8 @@ export function getAppListMin(
     options?: APIOptions,
     appName?: string,
     isJobView?: boolean,
+    offset: number = 0,
+    size?: number,
 ): Promise<AppListMin> {
     const queryString = new URLSearchParams()
     if (teamId) {
@@ -161,6 +163,13 @@ export function getAppListMin(
         queryString.set('appType', '2')
     }
 
+    if (offset) {
+        queryString.set('offset', offset.toString())
+    }
+    if (size) {
+        queryString.set('size', size.toString())
+    }
+
     return get(`${Routes.APP_LIST_MIN}?${queryString.toString()}`, options).then((response) => {
         let list = response?.result || []
         list = list.sort((a, b) => {
diff --git a/src/services/service.types.ts b/src/services/service.types.ts
index fd106cace3..4e66b4b749 100644
--- a/src/services/service.types.ts
+++ b/src/services/service.types.ts
@@ -62,10 +62,15 @@ export interface CDPipeline {
     isDeploymentBlocked?: boolean
 }
 
-export interface AppListMin extends ResponseType {
-    result?: { id: number; name: string }[]
+export interface AppListMinDTO {
+    id: number
+    name: string
+    createdBy: string
+    description: string
 }
 
+export type AppListMin = ResponseType<AppListMinDTO[]>
+
 export interface ProjectFilteredApps extends ResponseType {
     result?: {
         projectId: number
diff --git a/yarn.lock b/yarn.lock
index 1faa20ee0c..90e598895f 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1124,10 +1124,10 @@
   dependencies:
     "@jridgewell/trace-mapping" "0.3.9"
 
-"@devtron-labs/devtron-fe-common-lib@1.13.0-pre-6":
-  version "1.13.0-pre-6"
-  resolved "https://registry.yarnpkg.com/@devtron-labs/devtron-fe-common-lib/-/devtron-fe-common-lib-1.13.0-pre-6.tgz#eec6b658b6c656c860b4f6c55b10979f56b646fe"
-  integrity sha512-BOiT80SC8CzwueKe031FhdkbvrN/QyiZQRGP1XjsDwCsOxvEBcILICKKm5GeYfuIVsIbB8DaFiuLKXU5luJqCg==
+"@devtron-labs/devtron-fe-common-lib@1.13.0-pre-9":
+  version "1.13.0-pre-9"
+  resolved "https://registry.yarnpkg.com/@devtron-labs/devtron-fe-common-lib/-/devtron-fe-common-lib-1.13.0-pre-9.tgz#5e0ef129452659435546c0da67fb8191df317782"
+  integrity sha512-EU1cxbuSuYmdZ2yQoZZY+oq9mPGc9blsjek1vlqBk1brj8xIkDDI4M9CvQpBW5mcsvohdIHR9YFVHlmyDmoBHQ==
   dependencies:
     "@codemirror/lang-json" "6.0.1"
     "@codemirror/lang-yaml" "6.1.2"


Reviews:
user: login: AbhishekA1509
state: CHANGES_REQUESTED
author_association: MEMBER
submitted_at: 2025-05-14T07:59:53Z
user: login: shivani170
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-16T06:18:57Z
user: login: AbhishekA1509
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-16T10:26:13Z
user: login: AbhishekA1509
state: CHANGES_REQUESTED
author_association: MEMBER
submitted_at: 2025-05-16T12:36:45Z
user: login: AbhishekA1509
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-16T13:48:55Z
user: login: AbhishekA1509
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-16T13:51:04Z
user: login: AbhishekA1509
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-16T13:53:30Z
user: login: AbhishekA1509
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-16T13:54:52Z
user: login: AbhishekA1509
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-16T13:55:23Z
user: login: AbhishekA1509
state: DISMISSED
author_association: MEMBER
submitted_at: 2025-05-19T08:07:59Z
user: login: vivek-devtron
state: DISMISSED
author_association: CONTRIBUTOR
submitted_at: 2025-05-21T09:30:36Z
user: login: vivek-devtron
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-21T11:19:46Z

Review comments:
diff_hunk: @@ -0,0 +1,15 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
path: src/assets/icons/ic-devtron-job.svg
user: login: AbhishekA1509
body: Can we add in common?
created_at: 2025-05-14T06:49:02Z
author_association: MEMBER
diff_hunk: @@ -63,7 +63,7 @@ export interface CDPipeline {
 }
 
 export interface AppListMin extends ResponseType {
-    result?: { id: number; name: string }[]
+    result?: { id: number; name: string; createdBy: string; description: string }[]
path: src/services/service.types.ts
user: login: AbhishekA1509
body: Suggestion: `type AppListMin = ResponseType<AppListMinDTO[]>`
created_at: 2025-05-14T06:50:41Z
author_association: MEMBER
diff_hunk: @@ -358,6 +370,140 @@ const CreateAppModal = ({ isJobView, handleClose }: CreateAppModalProps) => {
         }
     }
 
+    const renderAppTemplateContent = () =>
+        formState.templateConfig ? (
+            <>
+                <div className="flex left dc__gap-12 py-12 px-20">
+                    <Button
+                        icon={<ICBack />}
+                        dataTestId="create-app-modal-go-back-to-templates-list"
+                        ariaLabel="go-back-to-templates-list"
+                        variant={ButtonVariantType.secondary}
+                        style={ButtonStyleType.neutral}
+                        size={ComponentSizeType.xs}
+                        showAriaLabelInTippy={false}
+                        onClick={goBackToTemplatesList}
+                    />
+                    <div className="flex left dc__gap-4">
+                        <Button
+                            dataTestId="template-list-breadcrumb"
+                            variant={ButtonVariantType.text}
+                            text="Templates"
+                            onClick={goBackToTemplatesList}
+                        />
+                        <span>/</span>
+                        <p className="m-0 flex left dc__gap-6">
+                            <ICAppTemplate className="icon-dim-20 p-1 dc__no-shrink" />
+                            <span className="fs-13 lh-20 fw-6 cn-9 dc__truncate">{formState.templateConfig.name}</span>
+                        </p>
+                    </div>
+                </div>
+                <div className="divider__secondary--horizontal" />
+                <div className="flexbox-col flex-grow-1 dc__overflow-auto create-app-modal__template">
+                    <div className="create-app-modal__template__loader">
+                        <Progressing size={32} />
+                    </div>
+                    <div className="create-app-modal__template__content flexbox-col dc__gap-20 flex-grow-1 bg__secondary dc__overflow-auto p-20">
+                        <ApplicationInfoForm
+                            formState={formState}
+                            handleFormStateChange={handleFormStateChange}
+                            formErrorState={formErrorState}
+                            handleTagErrorChange={handleTagErrorChange}
+                            isJobView={isJobView}
+                            selectedCreationMethod={selectedCreationMethod}
+                            isTagsAccordionExpanded={isTagsAccordionExpanded}
+                            toggleIsTagsAccordionExpanded={toggleIsTagsAccordionExpanded}
+                        />
+                        <UpdateTemplateConfig
+                            formState={formState}
+                            isJobView={isJobView}
+                            handleFormStateChange={handleFormStateChange}
+                            formErrorState={formErrorState}
+                        />
+                    </div>
+                </div>
+            </>
+        ) : (
+            TemplateList && <TemplateList handleTemplateClick={handleTemplateClick} />
+        )
+
+    const renderAppCloneContent = () =>
+        formState.cloneAppConfig ? (
+            <>
+                <div className="flex left dc__gap-12 py-12 px-20">
+                    <Button
+                        icon={<ICBack />}
+                        dataTestId="create-app-modal-go-back-to-clone-app-list"
+                        ariaLabel="go-back-to-clone-app-list"
+                        variant={ButtonVariantType.secondary}
+                        style={ButtonStyleType.neutral}
+                        size={ComponentSizeType.xs}
+                        showAriaLabelInTippy={false}
+                        onClick={goBackToAppCloneList}
+                    />
+                    <div className="flex left dc__gap-4">
+                        <Button
+                            dataTestId="clone-list-breadcrumb"
+                            variant={ButtonVariantType.text}
+                            text={isJobView ? 'Clone Job' : 'Clone Application'}
+                            onClick={goBackToAppCloneList}
+                        />
+                        <span>/</span>
+                        <p className="m-0 flex left dc__gap-6">
+                            {getAppConfig(isJobView ? APP_TYPE.JOB : APP_TYPE.DEVTRON_APPS, 20).icon}
+                            <span className="fs-13 lh-20 fw-6 cn-9 dc__truncate">
+                                {formState.cloneAppConfig.appName}
+                            </span>
+                        </p>
+                    </div>
+                </div>
+                <div className="divider__secondary--horizontal" />
+                <div className="flexbox-col flex-grow-1 dc__overflow-auto create-app-modal__template">
+                    <div className="create-app-modal__template__loader">
+                        <Progressing size={32} />
+                    </div>
+                    <div className="create-app-modal__template__content flexbox-col dc__gap-20 flex-grow-1 bg__secondary dc__overflow-auto p-20">
+                        <ApplicationInfoForm
+                            formState={formState}
+                            handleFormStateChange={handleFormStateChange}
+                            formErrorState={formErrorState}
+                            handleTagErrorChange={handleTagErrorChange}
+                            isJobView={isJobView}
+                            selectedCreationMethod={selectedCreationMethod}
+                            isTagsAccordionExpanded={isTagsAccordionExpanded}
+                            toggleIsTagsAccordionExpanded={toggleIsTagsAccordionExpanded}
+                        />
+                    </div>
+                </div>
+            </>
+        ) : (
+            <AppCloneList handleCloneAppClick={handleCloneAppClick} isJobView={isJobView} />
+        )
+
+    const getSelectedMethodContent = () => {
+        switch (selectedCreationMethod) {
+            case CreationMethodType.blank:
+                return (
+                    <ApplicationInfoForm
+                        formState={formState}
+                        handleFormStateChange={handleFormStateChange}
+                        formErrorState={formErrorState}
+                        handleTagErrorChange={handleTagErrorChange}
+                        isJobView={isJobView}
+                        selectedCreationMethod={selectedCreationMethod}
+                        isTagsAccordionExpanded={isTagsAccordionExpanded}
+                        toggleIsTagsAccordionExpanded={toggleIsTagsAccordionExpanded}
+                    />
+                )
+            case CreationMethodType.clone:
+                return renderAppCloneContent()
+            case CreationMethodType.template:
+                return renderAppTemplateContent()
+            default:
+                return null
+        }
+    }
+
     return (
         <Drawer position="right" width="1024px" onEscape={handleClose}>
path: src/Pages/App/CreateAppModal/CreateAppModal.component.tsx
user: login: AbhishekA1509
body: Should give onClose as well
created_at: 2025-05-14T07:02:06Z
author_association: MEMBER
diff_hunk: @@ -95,8 +98,6 @@ const CreateAppModal = ({ isJobView, handleClose }: CreateAppModalProps) => {
                 return validateDescription(value).message
             case 'projectId':
                 return validateProject(value).message
-            case 'cloneAppId':
path: src/Pages/App/CreateAppModal/CreateAppModal.component.tsx
user: login: AbhishekA1509
body: We should show error in toast case we have not selected app from list. Like we are showing for template:
'Please select a template to create app',
created_at: 2025-05-14T07:05:56Z
author_association: MEMBER
diff_hunk: @@ -358,6 +370,140 @@ const CreateAppModal = ({ isJobView, handleClose }: CreateAppModalProps) => {
         }
     }
 
+    const renderAppTemplateContent = () =>
+        formState.templateConfig ? (
+            <>
+                <div className="flex left dc__gap-12 py-12 px-20">
+                    <Button
+                        icon={<ICBack />}
+                        dataTestId="create-app-modal-go-back-to-templates-list"
+                        ariaLabel="go-back-to-templates-list"
+                        variant={ButtonVariantType.secondary}
+                        style={ButtonStyleType.neutral}
+                        size={ComponentSizeType.xs}
+                        showAriaLabelInTippy={false}
+                        onClick={goBackToTemplatesList}
+                    />
+                    <div className="flex left dc__gap-4">
+                        <Button
+                            dataTestId="template-list-breadcrumb"
+                            variant={ButtonVariantType.text}
+                            text="Templates"
+                            onClick={goBackToTemplatesList}
+                        />
+                        <span>/</span>
+                        <p className="m-0 flex left dc__gap-6">
+                            <ICAppTemplate className="icon-dim-20 p-1 dc__no-shrink" />
+                            <span className="fs-13 lh-20 fw-6 cn-9 dc__truncate">{formState.templateConfig.name}</span>
+                        </p>
+                    </div>
+                </div>
+                <div className="divider__secondary--horizontal" />
+                <div className="flexbox-col flex-grow-1 dc__overflow-auto create-app-modal__template">
+                    <div className="create-app-modal__template__loader">
+                        <Progressing size={32} />
+                    </div>
+                    <div className="create-app-modal__template__content flexbox-col dc__gap-20 flex-grow-1 bg__secondary dc__overflow-auto p-20">
+                        <ApplicationInfoForm
+                            formState={formState}
+                            handleFormStateChange={handleFormStateChange}
+                            formErrorState={formErrorState}
+                            handleTagErrorChange={handleTagErrorChange}
+                            isJobView={isJobView}
+                            selectedCreationMethod={selectedCreationMethod}
+                            isTagsAccordionExpanded={isTagsAccordionExpanded}
+                            toggleIsTagsAccordionExpanded={toggleIsTagsAccordionExpanded}
+                        />
+                        <UpdateTemplateConfig
+                            formState={formState}
+                            isJobView={isJobView}
+                            handleFormStateChange={handleFormStateChange}
+                            formErrorState={formErrorState}
+                        />
+                    </div>
+                </div>
+            </>
+        ) : (
+            TemplateList && <TemplateList handleTemplateClick={handleTemplateClick} />
+        )
+
+    const renderAppCloneContent = () =>
path: src/Pages/App/CreateAppModal/CreateAppModal.component.tsx
user: login: AbhishekA1509
body: Looks similar to renderAppTemplateContent can we combine both through props?
created_at: 2025-05-14T07:31:28Z
author_association: MEMBER
diff_hunk: @@ -30,6 +30,31 @@ const Sidebar = ({
         handleCreationMethodChange(creationMethod)
     }
 
+    const renderAppContent = () => (
+        <div className="flexbox-col dc__gap-24">
+            <p className="m-0" />
path: src/Pages/App/CreateAppModal/Sidebar.tsx
user: login: AbhishekA1509
body: Is this empty tag intentional? And can make array of messages and combine both array and job content
created_at: 2025-05-14T07:43:26Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2024. Devtron Inc.
+ */
+import { useEffect, useMemo, useRef } from 'react'
+
+import { abortPreviousRequests, GenericInfoCardListingProps, useAsync } from '@devtron-labs/devtron-fe-common-lib'
+
+import { getJobs } from '@Components/Jobs/Service'
+import { APP_TYPE } from '@Config/constants'
+import { getAppIconWithBackground } from '@Config/utils'
+import { getAppListMin } from '@Services/service'
+
+import { AppCloneListProps, DevtronListResponse } from './types'
+
+export const useDevtronCloneList = ({ handleCloneAppClick, isJobView, updatedList }: AppCloneListProps) => {
+    const cloneListAbortControllerRef = useRef(new AbortController())
+
+    const [isListLoading, listResponse, listError, reloadList] = useAsync<DevtronListResponse>(() =>
+        abortPreviousRequests(
+            () =>
+                isJobView
+                    ? getJobs(
+                          {
+                              teams: [],
+                              appStatuses: [],
+                              appNameSearch: '',
+                              offset: 0,
+                              size: 20,
+                              sortBy: 'appNameSort',
+                              sortOrder: 'ASC',
+                          },
+                          {
+                              signal: cloneListAbortControllerRef.current.signal,
+                          },
+                      ).then((res) => ({ type: APP_TYPE.JOB, data: res }))
+                    : getAppListMin(null, { signal: cloneListAbortControllerRef.current.signal }).then((res) => ({
+                          type: APP_TYPE.DEVTRON_APPS,
+                          data: res,
+                      })),
+            cloneListAbortControllerRef,
+        ),
+    )
+
+    useEffect(
+        () => () => {
+            cloneListAbortControllerRef.current.abort()
+        },
+        [],
+    )
+    let totalCount = 0
+
+    const list = useMemo(() => {
path: src/Pages/App/CreateAppModal/AppClone/useDevtronCloneList.tsx
user: login: AbhishekA1509
body: Should make this in service along with totalCount
created_at: 2025-05-14T07:47:59Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2024. Devtron Inc.
+ */
+import { useEffect, useMemo, useRef } from 'react'
+
+import { abortPreviousRequests, GenericInfoCardListingProps, useAsync } from '@devtron-labs/devtron-fe-common-lib'
+
+import { getJobs } from '@Components/Jobs/Service'
+import { APP_TYPE } from '@Config/constants'
+import { getAppIconWithBackground } from '@Config/utils'
+import { getAppListMin } from '@Services/service'
+
+import { AppCloneListProps, DevtronListResponse } from './types'
+
+export const useDevtronCloneList = ({ handleCloneAppClick, isJobView, updatedList }: AppCloneListProps) => {
+    const cloneListAbortControllerRef = useRef(new AbortController())
+
+    const [isListLoading, listResponse, listError, reloadList] = useAsync<DevtronListResponse>(() =>
+        abortPreviousRequests(
+            () =>
+                isJobView
+                    ? getJobs(
+                          {
+                              teams: [],
+                              appStatuses: [],
+                              appNameSearch: '',
+                              offset: 0,
+                              size: 20,
+                              sortBy: 'appNameSort',
+                              sortOrder: 'ASC',
+                          },
+                          {
+                              signal: cloneListAbortControllerRef.current.signal,
+                          },
+                      ).then((res) => ({ type: APP_TYPE.JOB, data: res }))
+                    : getAppListMin(null, { signal: cloneListAbortControllerRef.current.signal }).then((res) => ({
+                          type: APP_TYPE.DEVTRON_APPS,
+                          data: res,
+                      })),
+            cloneListAbortControllerRef,
+        ),
+    )
+
+    useEffect(
+        () => () => {
+            cloneListAbortControllerRef.current.abort()
+        },
+        [],
+    )
+    let totalCount = 0
+
+    const list = useMemo(() => {
+        if (isListLoading || !listResponse) return []
+
+        if (listResponse.type === APP_TYPE.JOB) {
+            const jobContainers = listResponse.data.result?.jobContainers || []
+            const updatedJobList = [...jobContainers, ...updatedList]
+
+            totalCount = listResponse.data.result.jobCount
+
+            return updatedJobList.map<GenericInfoCardListingProps['list'][number]>((job) => {
+                const { jobId, jobName, description } = job
+
+                return {
+                    id: String(jobId),
+                    title: jobName,
+                    description: description.description,
+                    author: description.createdBy,
+                    Icon: getAppIconWithBackground(APP_TYPE.JOB, 20),
+                    onClick: () => handleCloneAppClick({ appId: jobId, appName: jobName }),
+                }
+            })
+        }
+        const apps = listResponse.data.result || []
+
+        return apps.map<GenericInfoCardListingProps['list'][number]>((app) => {
+            const { id, name, createdBy, description } = app
+
+            return {
+                id: String(id),
+                title: name,
+                Icon: getAppIconWithBackground(APP_TYPE.DEVTRON_APPS, 20),
+                onClick: () => handleCloneAppClick({ appId: id, appName: name }),
+                author: createdBy,
+                description,
+            }
+        })
+    }, [isListLoading, listResponse, updatedList])
+
+    return {
+        isListLoading,
path: src/Pages/App/CreateAppModal/AppClone/useDevtronCloneList.tsx
user: login: AbhishekA1509
body: 
```suggestion
        isListLoading: isListLoading || getIsRequestAborted(listError),
```
created_at: 2025-05-14T07:49:17Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2024. Devtron Inc.
+ */
+import { useEffect, useMemo, useRef } from 'react'
+
+import { abortPreviousRequests, GenericInfoCardListingProps, useAsync } from '@devtron-labs/devtron-fe-common-lib'
+
+import { getJobs } from '@Components/Jobs/Service'
+import { APP_TYPE } from '@Config/constants'
+import { getAppIconWithBackground } from '@Config/utils'
+import { getAppListMin } from '@Services/service'
+
+import { AppCloneListProps, DevtronListResponse } from './types'
+
+export const useDevtronCloneList = ({ handleCloneAppClick, isJobView, updatedList }: AppCloneListProps) => {
+    const cloneListAbortControllerRef = useRef(new AbortController())
+
+    const [isListLoading, listResponse, listError, reloadList] = useAsync<DevtronListResponse>(() =>
+        abortPreviousRequests(
+            () =>
+                isJobView
+                    ? getJobs(
+                          {
+                              teams: [],
+                              appStatuses: [],
+                              appNameSearch: '',
+                              offset: 0,
+                              size: 20,
+                              sortBy: 'appNameSort',
+                              sortOrder: 'ASC',
+                          },
+                          {
+                              signal: cloneListAbortControllerRef.current.signal,
+                          },
+                      ).then((res) => ({ type: APP_TYPE.JOB, data: res }))
+                    : getAppListMin(null, { signal: cloneListAbortControllerRef.current.signal }).then((res) => ({
+                          type: APP_TYPE.DEVTRON_APPS,
+                          data: res,
+                      })),
+            cloneListAbortControllerRef,
+        ),
+    )
+
+    useEffect(
+        () => () => {
+            cloneListAbortControllerRef.current.abort()
+        },
+        [],
+    )
+    let totalCount = 0
+
+    const list = useMemo(() => {
+        if (isListLoading || !listResponse) return []
+
+        if (listResponse.type === APP_TYPE.JOB) {
+            const jobContainers = listResponse.data.result?.jobContainers || []
+            const updatedJobList = [...jobContainers, ...updatedList]
path: src/Pages/App/CreateAppModal/AppClone/useDevtronCloneList.tsx
user: login: AbhishekA1509
body: Instead of taking updatedList as prop should use from useAsync response and expose method to load more data and update the state since useAsync returns state setter at fifth index
created_at: 2025-05-14T07:56:58Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,109 @@
+import { useRef, useState } from 'react'
+
+import {
+    abortPreviousRequests,
+    ComponentSizeType,
+    DetectBottom,
+    GenericInfoCardBorderVariant,
+    GenericInfoCardListing,
+    GenericInfoListSkeleton,
+    SearchBar,
+    useStateFilters,
+} from '@devtron-labs/devtron-fe-common-lib'
+
+import { getJobs } from '@Components/Jobs/Service'
+import { JobContainerTypes } from '@Components/Jobs/Types'
+
+import { AppCloneListProps } from './types'
+import { useDevtronCloneList } from './useDevtronCloneList'
+
+export const AppCloneList = ({ handleCloneAppClick, isJobView }: AppCloneListProps) => {
+    const { searchKey, handleSearch, clearFilters } = useStateFilters()
+
+    const [updatedList, setUpdatedList] = useState<JobContainerTypes[]>([])
+
+    const { isListLoading, list, listError, reloadList, totalCount } = useDevtronCloneList({
+        handleCloneAppClick,
+        isJobView,
+        updatedList,
+    })
+    const [isLoadingMoreJobList, setIsLoadingMoreJobList] = useState<boolean>(false)
+    const [hasError, setHasError] = useState<boolean>(false)
+    const cloneListAbortControllerRef = useRef(new AbortController())
+
+    const hasMoreDataRef = useRef<boolean>(true)
path: src/Pages/App/CreateAppModal/AppClone/AppCloneList.tsx
user: login: AbhishekA1509
body: Should be variable -> `list.length < totalCount`
created_at: 2025-05-14T07:58:25Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,109 @@
+import { useRef, useState } from 'react'
+
+import {
+    abortPreviousRequests,
+    ComponentSizeType,
+    DetectBottom,
+    GenericInfoCardBorderVariant,
+    GenericInfoCardListing,
+    GenericInfoListSkeleton,
+    SearchBar,
+    useStateFilters,
+} from '@devtron-labs/devtron-fe-common-lib'
+
+import { getJobs } from '@Components/Jobs/Service'
+import { JobContainerTypes } from '@Components/Jobs/Types'
+
+import { AppCloneListProps } from './types'
+import { useDevtronCloneList } from './useDevtronCloneList'
+
+export const AppCloneList = ({ handleCloneAppClick, isJobView }: AppCloneListProps) => {
+    const { searchKey, handleSearch, clearFilters } = useStateFilters()
+
+    const [updatedList, setUpdatedList] = useState<JobContainerTypes[]>([])
+
+    const { isListLoading, list, listError, reloadList, totalCount } = useDevtronCloneList({
+        handleCloneAppClick,
+        isJobView,
+        updatedList,
+    })
+    const [isLoadingMoreJobList, setIsLoadingMoreJobList] = useState<boolean>(false)
+    const [hasError, setHasError] = useState<boolean>(false)
+    const cloneListAbortControllerRef = useRef(new AbortController())
+
+    const hasMoreDataRef = useRef<boolean>(true)
+
+    const handleLoadMore = async () => {
path: src/Pages/App/CreateAppModal/AppClone/AppCloneList.tsx
user: login: AbhishekA1509
body: Assuming this method will be deleted
created_at: 2025-05-14T07:58:56Z
author_association: MEMBER
diff_hunk: @@ -358,6 +370,140 @@ const CreateAppModal = ({ isJobView, handleClose }: CreateAppModalProps) => {
         }
     }
 
+    const renderAppTemplateContent = () =>
+        formState.templateConfig ? (
+            <>
+                <div className="flex left dc__gap-12 py-12 px-20">
+                    <Button
+                        icon={<ICBack />}
+                        dataTestId="create-app-modal-go-back-to-templates-list"
+                        ariaLabel="go-back-to-templates-list"
+                        variant={ButtonVariantType.secondary}
+                        style={ButtonStyleType.neutral}
+                        size={ComponentSizeType.xs}
+                        showAriaLabelInTippy={false}
+                        onClick={goBackToTemplatesList}
+                    />
+                    <div className="flex left dc__gap-4">
+                        <Button
+                            dataTestId="template-list-breadcrumb"
+                            variant={ButtonVariantType.text}
+                            text="Templates"
+                            onClick={goBackToTemplatesList}
+                        />
+                        <span>/</span>
+                        <p className="m-0 flex left dc__gap-6">
+                            <ICAppTemplate className="icon-dim-20 p-1 dc__no-shrink" />
+                            <span className="fs-13 lh-20 fw-6 cn-9 dc__truncate">{formState.templateConfig.name}</span>
+                        </p>
+                    </div>
+                </div>
+                <div className="divider__secondary--horizontal" />
+                <div className="flexbox-col flex-grow-1 dc__overflow-auto create-app-modal__template">
+                    <div className="create-app-modal__template__loader">
+                        <Progressing size={32} />
+                    </div>
+                    <div className="create-app-modal__template__content flexbox-col dc__gap-20 flex-grow-1 bg__secondary dc__overflow-auto p-20">
+                        <ApplicationInfoForm
+                            formState={formState}
+                            handleFormStateChange={handleFormStateChange}
+                            formErrorState={formErrorState}
+                            handleTagErrorChange={handleTagErrorChange}
+                            isJobView={isJobView}
+                            selectedCreationMethod={selectedCreationMethod}
+                            isTagsAccordionExpanded={isTagsAccordionExpanded}
+                            toggleIsTagsAccordionExpanded={toggleIsTagsAccordionExpanded}
+                        />
+                        <UpdateTemplateConfig
+                            formState={formState}
+                            isJobView={isJobView}
+                            handleFormStateChange={handleFormStateChange}
+                            formErrorState={formErrorState}
+                        />
+                    </div>
+                </div>
+            </>
+        ) : (
+            TemplateList && <TemplateList handleTemplateClick={handleTemplateClick} />
+        )
+
+    const renderAppCloneContent = () =>
+        formState.cloneAppConfig ? (
+            <>
+                <div className="flex left dc__gap-12 py-12 px-20">
+                    <Button
+                        icon={<ICBack />}
+                        dataTestId="create-app-modal-go-back-to-clone-app-list"
+                        ariaLabel="go-back-to-clone-app-list"
+                        variant={ButtonVariantType.secondary}
+                        style={ButtonStyleType.neutral}
+                        size={ComponentSizeType.xs}
+                        showAriaLabelInTippy={false}
+                        onClick={goBackToAppCloneList}
+                    />
+                    <div className="flex left dc__gap-4">
+                        <Button
+                            dataTestId="clone-list-breadcrumb"
+                            variant={ButtonVariantType.text}
+                            text={isJobView ? 'Clone Job' : 'Clone Application'}
+                            onClick={goBackToAppCloneList}
+                        />
+                        <span>/</span>
+                        <p className="m-0 flex left dc__gap-6">
+                            {getAppConfig(isJobView ? APP_TYPE.JOB : APP_TYPE.DEVTRON_APPS, 20).icon}
+                            <span className="fs-13 lh-20 fw-6 cn-9 dc__truncate">
+                                {formState.cloneAppConfig.appName}
+                            </span>
+                        </p>
+                    </div>
+                </div>
+                <div className="divider__secondary--horizontal" />
+                <div className="flexbox-col flex-grow-1 dc__overflow-auto create-app-modal__template">
+                    <div className="create-app-modal__template__loader">
+                        <Progressing size={32} />
+                    </div>
+                    <div className="create-app-modal__template__content flexbox-col dc__gap-20 flex-grow-1 bg__secondary dc__overflow-auto p-20">
+                        <ApplicationInfoForm
+                            formState={formState}
+                            handleFormStateChange={handleFormStateChange}
+                            formErrorState={formErrorState}
+                            handleTagErrorChange={handleTagErrorChange}
+                            isJobView={isJobView}
+                            selectedCreationMethod={selectedCreationMethod}
+                            isTagsAccordionExpanded={isTagsAccordionExpanded}
+                            toggleIsTagsAccordionExpanded={toggleIsTagsAccordionExpanded}
+                        />
+                    </div>
+                </div>
+            </>
+        ) : (
+            <AppCloneList handleCloneAppClick={handleCloneAppClick} isJobView={isJobView} />
+        )
+
+    const getSelectedMethodContent = () => {
+        switch (selectedCreationMethod) {
+            case CreationMethodType.blank:
+                return (
+                    <ApplicationInfoForm
+                        formState={formState}
+                        handleFormStateChange={handleFormStateChange}
+                        formErrorState={formErrorState}
+                        handleTagErrorChange={handleTagErrorChange}
+                        isJobView={isJobView}
+                        selectedCreationMethod={selectedCreationMethod}
+                        isTagsAccordionExpanded={isTagsAccordionExpanded}
+                        toggleIsTagsAccordionExpanded={toggleIsTagsAccordionExpanded}
+                    />
+                )
+            case CreationMethodType.clone:
+                return renderAppCloneContent()
+            case CreationMethodType.template:
+                return renderAppTemplateContent()
+            default:
+                return null
+        }
+    }
+
     return (
         <Drawer position="right" width="1024px" onEscape={handleClose}>
path: src/Pages/App/CreateAppModal/CreateAppModal.component.tsx
user: login: shivani170
body: It will close the modal on any click
created_at: 2025-05-16T06:18:56Z
author_association: CONTRIBUTOR
diff_hunk: @@ -358,6 +370,140 @@ const CreateAppModal = ({ isJobView, handleClose }: CreateAppModalProps) => {
         }
     }
 
+    const renderAppTemplateContent = () =>
+        formState.templateConfig ? (
+            <>
+                <div className="flex left dc__gap-12 py-12 px-20">
+                    <Button
+                        icon={<ICBack />}
+                        dataTestId="create-app-modal-go-back-to-templates-list"
+                        ariaLabel="go-back-to-templates-list"
+                        variant={ButtonVariantType.secondary}
+                        style={ButtonStyleType.neutral}
+                        size={ComponentSizeType.xs}
+                        showAriaLabelInTippy={false}
+                        onClick={goBackToTemplatesList}
+                    />
+                    <div className="flex left dc__gap-4">
+                        <Button
+                            dataTestId="template-list-breadcrumb"
+                            variant={ButtonVariantType.text}
+                            text="Templates"
+                            onClick={goBackToTemplatesList}
+                        />
+                        <span>/</span>
+                        <p className="m-0 flex left dc__gap-6">
+                            <ICAppTemplate className="icon-dim-20 p-1 dc__no-shrink" />
+                            <span className="fs-13 lh-20 fw-6 cn-9 dc__truncate">{formState.templateConfig.name}</span>
+                        </p>
+                    </div>
+                </div>
+                <div className="divider__secondary--horizontal" />
+                <div className="flexbox-col flex-grow-1 dc__overflow-auto create-app-modal__template">
+                    <div className="create-app-modal__template__loader">
+                        <Progressing size={32} />
+                    </div>
+                    <div className="create-app-modal__template__content flexbox-col dc__gap-20 flex-grow-1 bg__secondary dc__overflow-auto p-20">
+                        <ApplicationInfoForm
+                            formState={formState}
+                            handleFormStateChange={handleFormStateChange}
+                            formErrorState={formErrorState}
+                            handleTagErrorChange={handleTagErrorChange}
+                            isJobView={isJobView}
+                            selectedCreationMethod={selectedCreationMethod}
+                            isTagsAccordionExpanded={isTagsAccordionExpanded}
+                            toggleIsTagsAccordionExpanded={toggleIsTagsAccordionExpanded}
+                        />
+                        <UpdateTemplateConfig
+                            formState={formState}
+                            isJobView={isJobView}
+                            handleFormStateChange={handleFormStateChange}
+                            formErrorState={formErrorState}
+                        />
+                    </div>
+                </div>
+            </>
+        ) : (
+            TemplateList && <TemplateList handleTemplateClick={handleTemplateClick} />
+        )
+
+    const renderAppCloneContent = () =>
+        formState.cloneAppConfig ? (
+            <>
+                <div className="flex left dc__gap-12 py-12 px-20">
+                    <Button
+                        icon={<ICBack />}
+                        dataTestId="create-app-modal-go-back-to-clone-app-list"
+                        ariaLabel="go-back-to-clone-app-list"
+                        variant={ButtonVariantType.secondary}
+                        style={ButtonStyleType.neutral}
+                        size={ComponentSizeType.xs}
+                        showAriaLabelInTippy={false}
+                        onClick={goBackToAppCloneList}
+                    />
+                    <div className="flex left dc__gap-4">
+                        <Button
+                            dataTestId="clone-list-breadcrumb"
+                            variant={ButtonVariantType.text}
+                            text={isJobView ? 'Clone Job' : 'Clone Application'}
+                            onClick={goBackToAppCloneList}
+                        />
+                        <span>/</span>
+                        <p className="m-0 flex left dc__gap-6">
+                            {getAppConfig(isJobView ? APP_TYPE.JOB : APP_TYPE.DEVTRON_APPS, 20).icon}
+                            <span className="fs-13 lh-20 fw-6 cn-9 dc__truncate">
+                                {formState.cloneAppConfig.appName}
+                            </span>
+                        </p>
+                    </div>
+                </div>
+                <div className="divider__secondary--horizontal" />
+                <div className="flexbox-col flex-grow-1 dc__overflow-auto create-app-modal__template">
+                    <div className="create-app-modal__template__loader">
+                        <Progressing size={32} />
+                    </div>
+                    <div className="create-app-modal__template__content flexbox-col dc__gap-20 flex-grow-1 bg__secondary dc__overflow-auto p-20">
+                        <ApplicationInfoForm
+                            formState={formState}
+                            handleFormStateChange={handleFormStateChange}
+                            formErrorState={formErrorState}
+                            handleTagErrorChange={handleTagErrorChange}
+                            isJobView={isJobView}
+                            selectedCreationMethod={selectedCreationMethod}
+                            isTagsAccordionExpanded={isTagsAccordionExpanded}
+                            toggleIsTagsAccordionExpanded={toggleIsTagsAccordionExpanded}
+                        />
+                    </div>
+                </div>
+            </>
+        ) : (
+            <AppCloneList handleCloneAppClick={handleCloneAppClick} isJobView={isJobView} />
+        )
+
+    const getSelectedMethodContent = () => {
+        switch (selectedCreationMethod) {
+            case CreationMethodType.blank:
+                return (
+                    <ApplicationInfoForm
+                        formState={formState}
+                        handleFormStateChange={handleFormStateChange}
+                        formErrorState={formErrorState}
+                        handleTagErrorChange={handleTagErrorChange}
+                        isJobView={isJobView}
+                        selectedCreationMethod={selectedCreationMethod}
+                        isTagsAccordionExpanded={isTagsAccordionExpanded}
+                        toggleIsTagsAccordionExpanded={toggleIsTagsAccordionExpanded}
+                    />
+                )
+            case CreationMethodType.clone:
+                return renderAppCloneContent()
+            case CreationMethodType.template:
+                return renderAppTemplateContent()
+            default:
+                return null
+        }
+    }
+
     return (
         <Drawer position="right" width="1024px" onEscape={handleClose}>
path: src/Pages/App/CreateAppModal/CreateAppModal.component.tsx
user: login: AbhishekA1509
body: Can add stopPropagation on parent div
created_at: 2025-05-16T10:26:12Z
author_association: MEMBER
diff_hunk: @@ -36,20 +35,20 @@ export const getResourceKindFromAppType = (appType: AppOverviewProps['appType'])
     }
 }
 
-export const getAppConfig = (appType: AppOverviewProps['appType']) => {
+export const getAppConfig = (appType: AppOverviewProps['appType'], iconSize: IconBaseSizeType = 48) => {
     switch (appType) {
path: src/components/app/Overview/utils.tsx
user: login: AbhishekA1509
body: Suggestion:
```suggestion
    const icon = getAppIconWithBackground(appType, iconSize)
    switch (appType) {
```
created_at: 2025-05-16T11:54:18Z
author_association: MEMBER
diff_hunk: @@ -30,6 +30,31 @@ const Sidebar = ({
         handleCreationMethodChange(creationMethod)
     }
 
+    const renderAppContent = () => (
+        <div className="flexbox-col dc__gap-24">
+            <p className="m-0" />
path: src/Pages/App/CreateAppModal/Sidebar.tsx
user: login: AbhishekA1509
body: Can combine both methods or move `<div className="flexbox-col dc__gap-24">` on line 86
created_at: 2025-05-16T11:58:55Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2024. Devtron Inc.
+ */
+import { useEffect, useMemo, useRef, useState } from 'react'
+
+import {
+    abortPreviousRequests,
+    GenericInfoCardListingProps,
+    getIsRequestAborted,
+    useAsync,
+} from '@devtron-labs/devtron-fe-common-lib'
+
+import { getJobs } from '@Components/Jobs/Service'
+import { APP_TYPE } from '@Config/constants'
+import { getAppIconWithBackground } from '@Config/utils'
+import { getAppListMin } from '@Services/service'
+
+import { DevtronAppCloneListProps, DevtronListResponse } from './types'
+
+export const useDevtronCloneList = ({ handleCloneAppClick, isJobView }: DevtronAppCloneListProps) => {
+    const cloneListAbortControllerRef = useRef(new AbortController())
+    const [isLoadingMore, setIsLoadingMore] = useState(false)
+
+    const [isListLoading, listResponse, listError, reloadList, setListResponse] = useAsync<DevtronListResponse>(() =>
+        abortPreviousRequests(
+            () =>
+                isJobView
+                    ? getJobs(
+                          {
+                              teams: [],
+                              appStatuses: [],
+                              appNameSearch: '',
+                              offset: 0,
+                              size: 20,
+                              sortBy: 'appNameSort',
+                              sortOrder: 'ASC',
+                          },
+                          {
+                              signal: cloneListAbortControllerRef.current.signal,
+                          },
+                      ).then((res) => ({ type: APP_TYPE.JOB, data: res }))
+                    : getAppListMin(null, { signal: cloneListAbortControllerRef.current.signal }).then((res) => ({
+                          type: APP_TYPE.DEVTRON_APPS,
+                          data: res,
+                      })),
+            cloneListAbortControllerRef,
+        ),
+    )
+
+    useEffect(
+        () => () => {
+            cloneListAbortControllerRef.current.abort()
+        },
+        [],
+    )
+    let totalCount = 0
+
+    if (listResponse?.type === APP_TYPE.JOB) {
+        totalCount = listResponse.data.result.jobCount
+    }
+
+    const loadMoreData = async () => {
+        if (isLoadingMore || !listResponse) return
+
+        setIsLoadingMore(true)
+        try {
+            if (listResponse.type === APP_TYPE.JOB) {
+                const currentJobContainers = listResponse.data.result?.jobContainers ?? []
+
+                const response = await getJobs(
+                    {
+                        teams: [],
+                        appStatuses: [],
+                        appNameSearch: '',
+                        offset: currentJobContainers.length,
+                        size: 20,
+                        sortBy: 'appNameSort',
+                        sortOrder: 'ASC',
+                    },
+                    {
+                        signal: cloneListAbortControllerRef.current.signal,
+                    },
+                )
+
+                const newJobContainers = response.result?.jobContainers ?? []
+
+                // Update the list response with the new data
+                setListResponse({
+                    type: APP_TYPE.JOB,
+                    data: {
+                        ...response,
+                        result: {
+                            ...response.result,
+                            jobContainers: [...currentJobContainers, ...newJobContainers],
+                        },
+                    },
+                })
+            }
+        } finally {
path: src/Pages/App/CreateAppModal/AppClone/useDevtronCloneList.tsx
user: login: AbhishekA1509
body: Missing catch
created_at: 2025-05-16T12:15:55Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2024. Devtron Inc.
+ */
+import { useEffect, useMemo, useRef, useState } from 'react'
+
+import {
+    abortPreviousRequests,
+    GenericInfoCardListingProps,
+    getIsRequestAborted,
+    useAsync,
+} from '@devtron-labs/devtron-fe-common-lib'
+
+import { getJobs } from '@Components/Jobs/Service'
+import { APP_TYPE } from '@Config/constants'
+import { getAppIconWithBackground } from '@Config/utils'
+import { getAppListMin } from '@Services/service'
+
+import { DevtronAppCloneListProps, DevtronListResponse } from './types'
+
+export const useDevtronCloneList = ({ handleCloneAppClick, isJobView }: DevtronAppCloneListProps) => {
+    const cloneListAbortControllerRef = useRef(new AbortController())
+    const [isLoadingMore, setIsLoadingMore] = useState(false)
+
+    const [isListLoading, listResponse, listError, reloadList, setListResponse] = useAsync<DevtronListResponse>(() =>
+        abortPreviousRequests(
+            () =>
+                isJobView
+                    ? getJobs(
+                          {
+                              teams: [],
+                              appStatuses: [],
+                              appNameSearch: '',
+                              offset: 0,
+                              size: 20,
+                              sortBy: 'appNameSort',
+                              sortOrder: 'ASC',
+                          },
+                          {
+                              signal: cloneListAbortControllerRef.current.signal,
+                          },
+                      ).then((res) => ({ type: APP_TYPE.JOB, data: res }))
+                    : getAppListMin(null, { signal: cloneListAbortControllerRef.current.signal }).then((res) => ({
+                          type: APP_TYPE.DEVTRON_APPS,
+                          data: res,
+                      })),
+            cloneListAbortControllerRef,
+        ),
+    )
+
+    useEffect(
+        () => () => {
+            cloneListAbortControllerRef.current.abort()
+        },
+        [],
+    )
+    let totalCount = 0
+
+    if (listResponse?.type === APP_TYPE.JOB) {
+        totalCount = listResponse.data.result.jobCount
+    }
+
+    const loadMoreData = async () => {
+        if (isLoadingMore || !listResponse) return
+
+        setIsLoadingMore(true)
+        try {
+            if (listResponse.type === APP_TYPE.JOB) {
+                const currentJobContainers = listResponse.data.result?.jobContainers ?? []
+
+                const response = await getJobs(
+                    {
+                        teams: [],
+                        appStatuses: [],
+                        appNameSearch: '',
+                        offset: currentJobContainers.length,
+                        size: 20,
+                        sortBy: 'appNameSort',
+                        sortOrder: 'ASC',
+                    },
+                    {
+                        signal: cloneListAbortControllerRef.current.signal,
path: src/Pages/App/CreateAppModal/AppClone/useDevtronCloneList.tsx
user: login: AbhishekA1509
body: Stale signal
created_at: 2025-05-16T12:16:35Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2024. Devtron Inc.
+ */
+import { useEffect, useMemo, useRef, useState } from 'react'
+
+import {
+    abortPreviousRequests,
+    GenericInfoCardListingProps,
+    getIsRequestAborted,
+    useAsync,
+} from '@devtron-labs/devtron-fe-common-lib'
+
+import { getJobs } from '@Components/Jobs/Service'
+import { APP_TYPE } from '@Config/constants'
+import { getAppIconWithBackground } from '@Config/utils'
+import { getAppListMin } from '@Services/service'
+
+import { DevtronAppCloneListProps, DevtronListResponse } from './types'
+
+export const useDevtronCloneList = ({ handleCloneAppClick, isJobView }: DevtronAppCloneListProps) => {
+    const cloneListAbortControllerRef = useRef(new AbortController())
+    const [isLoadingMore, setIsLoadingMore] = useState(false)
+
+    const [isListLoading, listResponse, listError, reloadList, setListResponse] = useAsync<DevtronListResponse>(() =>
+        abortPreviousRequests(
path: src/Pages/App/CreateAppModal/AppClone/useDevtronCloneList.tsx
user: login: AbhishekA1509
body: Should create a wrapper method including abortPreviousRequests and re-use in loadMore
created_at: 2025-05-16T12:17:08Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,91 @@
+import { useState } from 'react'
+
+import {
+    Button,
+    ComponentSizeType,
+    DetectBottom,
+    GenericInfoCardBorderVariant,
+    GenericInfoCardListing,
+    GenericInfoListSkeleton,
+    Icon,
+    SearchBar,
+    useStateFilters,
+} from '@devtron-labs/devtron-fe-common-lib'
+
+import { CreationMethodType } from '../types'
+import { AppCloneListProps } from './types'
+import { useDevtronCloneList } from './useDevtronCloneList'
+
+export const AppCloneList = ({ handleCloneAppClick, isJobView, handleCreationMethodChange }: AppCloneListProps) => {
+    const { searchKey, handleSearch, clearFilters } = useStateFilters()
+    const [isLoadingMoreJobList, setIsLoadingMoreJobList] = useState<boolean>(false)
+    const [hasError, setHasError] = useState<boolean>(false)
+
+    const { isListLoading, list, listError, reloadList, loadMoreData, hasMoreData } = useDevtronCloneList({
+        handleCloneAppClick,
path: src/Pages/App/CreateAppModal/AppClone/AppCloneList.tsx
user: login: AbhishekA1509
body: In case of job i believe the search key needs to go to API
created_at: 2025-05-16T12:20:02Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,91 @@
+import { useState } from 'react'
+
+import {
+    Button,
+    ComponentSizeType,
+    DetectBottom,
+    GenericInfoCardBorderVariant,
+    GenericInfoCardListing,
+    GenericInfoListSkeleton,
+    Icon,
+    SearchBar,
+    useStateFilters,
+} from '@devtron-labs/devtron-fe-common-lib'
+
+import { CreationMethodType } from '../types'
+import { AppCloneListProps } from './types'
+import { useDevtronCloneList } from './useDevtronCloneList'
+
+export const AppCloneList = ({ handleCloneAppClick, isJobView, handleCreationMethodChange }: AppCloneListProps) => {
+    const { searchKey, handleSearch, clearFilters } = useStateFilters()
+    const [isLoadingMoreJobList, setIsLoadingMoreJobList] = useState<boolean>(false)
+    const [hasError, setHasError] = useState<boolean>(false)
path: src/Pages/App/CreateAppModal/AppClone/AppCloneList.tsx
user: login: AbhishekA1509
body: We already have this state in useDevtronCloneList, should expose the state from the hook
created_at: 2025-05-16T12:20:35Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,174 @@
+import {
+    BaseAppMetaData,
+    Button,
+    ButtonStyleType,
+    ButtonVariantType,
+    ComponentSizeType,
+    Icon,
+    Progressing,
+} from '@devtron-labs/devtron-fe-common-lib'
+
+import { importComponentFromFELibrary } from '@Components/common'
+import { APP_TYPE } from '@Config/constants'
+import { getAppIconWithBackground } from '@Config/utils'
+
+import { AppCloneList } from './AppClone'
+import ApplicationInfoForm from './ApplicationInfoForm'
+import {
+    ApplicationSelectionListProps,
+    CreateAppFormStateActionType,
+    CreateAppFormStateType,
+    CreationMethodType,
+} from './types'
+import UpdateTemplateConfig from './UpdateTemplateConfig'
+
+const TemplateList = importComponentFromFELibrary('TemplateList', null, 'function')
+
+export const CloneApplicationSelectionList = ({
+    formState,
+    selectedCreationMethod,
+    isJobView,
+    handleFormStateChange,
+    formErrorState,
+    handleTagErrorChange,
+    isTagsAccordionExpanded,
+    toggleIsTagsAccordionExpanded,
+    handleCreationMethodChange,
+}: ApplicationSelectionListProps) => {
+    const isCreationMethodTemplate = selectedCreationMethod === CreationMethodType.template
+
+    const goBackToTemplatesList = () =>
+        handleFormStateChange({
+            action: CreateAppFormStateActionType.updateTemplateConfig,
+            value: null,
+        })
+
+    const goBackToAppCloneList = () =>
+        handleFormStateChange({
+            action: CreateAppFormStateActionType.updateCloneAppConfig,
+            value: null,
+        })
+
path: src/Pages/App/CreateAppModal/CloneApplicationSelectionList.tsx
user: login: AbhishekA1509
body: 
```suggestion

    const handleGoBack = () => {
        handleFormStateChange({
            action: isCreationMethodTemplate ? CreateAppFormStateActionType.updateTemplateConfig: CreateAppFormStateActionType.updateCloneAppConfig,
            value: null,
        })
    }

```
created_at: 2025-05-16T12:29:06Z
author_association: MEMBER
diff_hunk: @@ -289,10 +251,10 @@ const CreateAppModal = ({ isJobView, handleClose }: CreateAppModalProps) => {
         const { isFormValid, invalidLabels, labelTags, invalidWorkFlow } = validateForm()
 
         if (isCreationMethodTemplate) {
-            if (!formState.templateConfig?.templateId) {
+            if (!formState.templateConfig?.templateId || !formState.cloneAppConfig?.appId) {
path: src/Pages/App/CreateAppModal/CreateAppModal.component.tsx
user: login: AbhishekA1509
body: No need to check !formState.cloneAppConfig?.appId since isCreationMethodTemplate should be false in case we are on clone app tab
created_at: 2025-05-16T12:32:39Z
author_association: MEMBER
diff_hunk: @@ -358,92 +327,67 @@ const CreateAppModal = ({ isJobView, handleClose }: CreateAppModalProps) => {
         }
     }
 
+    const handleCreationMethodChange = (method: CreationMethodType) => {
+        setFormState((prev) => ({
path: src/Pages/App/CreateAppModal/CreateAppModal.component.tsx
user: login: AbhishekA1509
body: Should call handleFormStateChange since that is meant to be single mutator for this state
created_at: 2025-05-16T12:35:23Z
author_association: MEMBER
diff_hunk: @@ -41,7 +41,7 @@ const UpdateTemplateConfig = ({
     handleFormStateChange,
     formErrorState,
 }: UpdateTemplateConfigProps) => {
-    const stringTemplateDbId = formState.templateConfig.id.toString()
+    const stringTemplateDbId = formState.templateConfig?.id.toString()
path: src/Pages/App/CreateAppModal/UpdateTemplateConfig.tsx
user: login: AbhishekA1509
body: Is null check intentional? since earlier that seems to be working fine?
created_at: 2025-05-16T12:36:40Z
author_association: MEMBER
diff_hunk: @@ -36,20 +35,21 @@ export const getResourceKindFromAppType = (appType: AppOverviewProps['appType'])
     }
 }
 
-export const getAppConfig = (appType: AppOverviewProps['appType']) => {
+export const getAppConfig = (appType: AppOverviewProps['appType'], iconSize: IconBaseSizeType = 48) => {
+    const icon = getAppIconWithBackground(appType, iconSize)
     switch (appType) {
         case 'app':
             return {
                 resourceName: 'application',
                 defaultNote: DefaultAppNote,
-                icon: <AppIcon className="icon-dim-48" />,
+                icon: icon,
                 defaultDescription: APP_DESCRIPTION,
             }
         case 'job':
             return {
                 resourceName: 'job',
                 defaultNote: DefaultJobNote,
-                icon: <JobIcon className="icon-dim-48 dc__icon-bg-color br-4 p-8" />,
+                icon: icon,
path: src/components/app/Overview/utils.tsx
user: login: AbhishekA1509
body: 
```suggestion
                icon,
                defaultDescription: APP_DESCRIPTION,
            }
        case 'job':
            return {
                resourceName: 'job',
                defaultNote: DefaultJobNote,
                icon,
```
created_at: 2025-05-16T13:48:54Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,80 @@
+import {
+    Button,
+    ComponentSizeType,
+    DetectBottom,
+    GenericInfoCardBorderVariant,
+    GenericInfoCardListing,
+    GenericInfoListSkeleton,
+    Icon,
+    SearchBar,
+    useStateFilters,
+} from '@devtron-labs/devtron-fe-common-lib'
+
+import { CreationMethodType } from '../types'
+import { AppCloneListProps } from './types'
+import { useDevtronCloneList } from './useDevtronCloneList'
+
+export const AppCloneList = ({ handleCloneAppClick, isJobView, handleCreationMethodChange }: AppCloneListProps) => {
+    const { searchKey, handleSearch, clearFilters } = useStateFilters()
path: src/Pages/App/CreateAppModal/AppClone/AppCloneList.tsx
user: login: AbhishekA1509
body: This state will be different from payload in useDevtronCloneList since we have called the useStateFilters twice which will create two separate states
created_at: 2025-05-16T13:51:01Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2024. Devtron Inc.
+ */
+import { useEffect, useMemo, useRef, useState } from 'react'
+
+import {
+    abortPreviousRequests,
+    getIsRequestAborted,
+    showError,
+    useAsync,
+    useStateFilters,
+} from '@devtron-labs/devtron-fe-common-lib'
+
+import { getJobs } from '@Components/Jobs/Service'
+import { APP_TYPE } from '@Config/constants'
+import { getAppListMin } from '@Services/service'
+
+import { getDevtronAppList } from '../service'
+import { DevtronAppCloneListProps, DevtronListResponse } from './types'
+
+export const useDevtronCloneList = ({ handleCloneAppClick, isJobView }: DevtronAppCloneListProps) => {
+    const cloneListAbortControllerRef = useRef(new AbortController())
+    const [isLoadingMore, setIsLoadingMore] = useState(false)
+    const [hasError, setHasError] = useState(false)
+    const { searchKey } = useStateFilters()
+
+    const fetchDevtronCloneList = (offset = 0): Promise<DevtronListResponse> =>
+        abortPreviousRequests(
+            () =>
+                isJobView
+                    ? getJobs(
+                          {
+                              teams: [],
+                              appStatuses: [],
+                              appNameSearch: '',
+                              offset,
+                              size: 20,
+                              sortBy: 'appNameSort',
+                              sortOrder: 'ASC',
+                              searchKey,
+                          },
+                          {
+                              signal: cloneListAbortControllerRef.current.signal,
+                          },
+                      ).then((res) => ({ type: APP_TYPE.JOB, data: res }))
+                    : getAppListMin(null, { signal: cloneListAbortControllerRef.current.signal }).then((res) => ({
+                          type: APP_TYPE.DEVTRON_APPS,
+                          data: res,
+                      })),
path: src/Pages/App/CreateAppModal/AppClone/useDevtronCloneList.tsx
user: login: AbhishekA1509
body: We should create a service for this block and move the list and totalCount computation inside the serive itself
```suggestion
                isJobView
                    ? getJobs(
                          {
                              teams: [],
                              appStatuses: [],
                              appNameSearch: '',
                              offset,
                              size: 20,
                              sortBy: 'appNameSort',
                              sortOrder: 'ASC',
                              searchKey,
                          },
                          {
                              signal: cloneListAbortControllerRef.current.signal,
                          },
                      ).then((res) => ({ type: APP_TYPE.JOB, data: res }))
                    : getAppListMin(null, { signal: cloneListAbortControllerRef.current.signal }).then((res) => ({
                          type: APP_TYPE.DEVTRON_APPS,
                          data: res,
                      })),
```
created_at: 2025-05-16T13:53:28Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2024. Devtron Inc.
+ */
+import { useEffect, useMemo, useRef, useState } from 'react'
+
+import {
+    abortPreviousRequests,
+    getIsRequestAborted,
+    showError,
+    useAsync,
+    useStateFilters,
+} from '@devtron-labs/devtron-fe-common-lib'
+
+import { getJobs } from '@Components/Jobs/Service'
+import { APP_TYPE } from '@Config/constants'
+import { getAppListMin } from '@Services/service'
+
+import { getDevtronAppList } from '../service'
+import { DevtronAppCloneListProps, DevtronListResponse } from './types'
+
+export const useDevtronCloneList = ({ handleCloneAppClick, isJobView }: DevtronAppCloneListProps) => {
+    const cloneListAbortControllerRef = useRef(new AbortController())
+    const [isLoadingMore, setIsLoadingMore] = useState(false)
+    const [hasError, setHasError] = useState(false)
+    const { searchKey } = useStateFilters()
+
+    const fetchDevtronCloneList = (offset = 0): Promise<DevtronListResponse> =>
+        abortPreviousRequests(
+            () =>
+                isJobView
+                    ? getJobs(
+                          {
+                              teams: [],
+                              appStatuses: [],
+                              appNameSearch: '',
+                              offset,
+                              size: 20,
+                              sortBy: 'appNameSort',
+                              sortOrder: 'ASC',
+                              searchKey,
+                          },
+                          {
+                              signal: cloneListAbortControllerRef.current.signal,
+                          },
+                      ).then((res) => ({ type: APP_TYPE.JOB, data: res }))
+                    : getAppListMin(null, { signal: cloneListAbortControllerRef.current.signal }).then((res) => ({
+                          type: APP_TYPE.DEVTRON_APPS,
+                          data: res,
+                      })),
+            cloneListAbortControllerRef,
+        )
+
+    const [isListLoading, listResponse, listError, reloadList, setListResponse] = useAsync<DevtronListResponse>(() =>
+        fetchDevtronCloneList(0),
+    )
+
+    useEffect(
+        () => () => {
+            cloneListAbortControllerRef.current.abort()
+        },
+        [],
+    )
+
+    const { list, totalCount } = useMemo(() => {
+        if (!listResponse) return { list: [], totalCount: 0 }
+        return getDevtronAppList({ listResponse, handleCloneAppClick })
+    }, [isListLoading, listResponse, handleCloneAppClick])
+
+    const loadMoreData = async () => {
+        if (isLoadingMore || !listResponse) return
+
+        setIsLoadingMore(true)
+        try {
+            if (listResponse.type === APP_TYPE.JOB) {
+                const currentJobContainers = listResponse.data.result?.jobContainers ?? []
+
+                const response: DevtronListResponse = await fetchDevtronCloneList(currentJobContainers.length)
+
+                // Update the list response with the new data
+                setListResponse({
+                    type: APP_TYPE.JOB,
+                    data: {
+                        ...response,
+                        result: {
+                            ...response.data,
+                            jobContainers: [
+                                ...currentJobContainers,
+                                ...('jobContainers' in response.data.result
+                                    ? response.data.result.jobContainers || []
+                                    : []),
+                            ],
+                        },
+                    },
+                })
+            }
+        } catch (error) {
+            setHasError(true)
+            showError(error)
+        } finally {
+            setIsLoadingMore(false)
+        }
+    }
+
+    return {
+        isListLoading: isListLoading ?? getIsRequestAborted(listError),
path: src/Pages/App/CreateAppModal/AppClone/useDevtronCloneList.tsx
user: login: AbhishekA1509
body: This is supposed to || only since ?? will not work if isListLoading is false
created_at: 2025-05-16T13:54:50Z
author_association: MEMBER
diff_hunk: @@ -30,6 +30,31 @@ const Sidebar = ({
         handleCreationMethodChange(creationMethod)
     }
 
+    const renderAppContent = () => (
+        <div className="flexbox-col dc__gap-24">
+            <p className="m-0" />
path: src/Pages/App/CreateAppModal/Sidebar.tsx
user: login: AbhishekA1509
body: Not resolved yet
created_at: 2025-05-16T13:55:23Z
author_association: MEMBER

PR comments:
user: login: sonarqubecloud[bot]
created_at: 2025-05-21T11:21:36Z
body: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=devtron-labs_dashboard&pullRequest=2705) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [2 New issues](https://sonarcloud.io/project/issues?id=devtron-labs_dashboard&pullRequest=2705&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=devtron-labs_dashboard&pullRequest=2705&issueStatuses=ACCEPTED)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=devtron-labs_dashboard&pullRequest=2705&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=devtron-labs_dashboard&pullRequest=2705&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=devtron-labs_dashboard&pullRequest=2705&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=devtron-labs_dashboard&pullRequest=2705)


author_association: NONE