@@ -54,6 +54,9 @@ import { getBrandingConfig } from "../../redux/selectors/configSelectors";
5454import { messageInstance } from "lowcoder-design/src/components/GlobalInstances" ;
5555import { EditorContext } from "../../comps/editorState" ;
5656import Tooltip from "antd/es/tooltip" ;
57+ import { LockOutlined } from '@ant-design/icons' ;
58+ import Avatar from 'antd/es/avatar' ;
59+
5760
5861const StyledLink = styled . a `
5962 display: flex;
@@ -234,12 +237,6 @@ const DropdownStyled = styled(Dropdown)`
234237 }
235238` ;
236239
237- const DropdownMenuStyled = styled ( DropdownMenu ) `
238- .ant-dropdown-menu-item:hover {
239- background: #edf4fa;
240- }
241- ` ;
242-
243240const Wrapper = styled . div `
244241 .taco-edit-text-wrapper {
245242 width: fit-content;
@@ -262,6 +259,16 @@ const Prefix = styled.div`
262259 }
263260` ;
264261
262+ // Add the lock icon logic for disabled options
263+ const DropdownMenuStyled = styled ( DropdownMenu ) `
264+ .ant-dropdown-menu-item:hover {
265+ background:${ ( props ) =>
266+ props . disabled ?'inherit' :'#edf4fa' } ;
267+ cursor:${ ( props ) =>
268+ props . disabled ?'not-allowed' :'pointer' } ;
269+ }
270+ ` ;
271+
265272function HeaderProfile ( props :{ user :User } ) {
266273const { user} = props ;
267274const fetchingUser = useSelector ( isFetchingUser ) ;
@@ -318,6 +325,10 @@ export default function Header(props: HeaderProps) {
318325
319326const isModule = appType === AppTypeEnum . Module ;
320327
328+ // Raheel: Todo - get concurrent editing state by API
329+ // maybe via editorState.getConcurrentAppEditingState(); as a new function?
330+ const [ concurrentAppEditingState , setConcurrentAppEditingState ] = useState ( true ) ;
331+
321332const editorModeOptions = [
322333{
323334label :trans ( "header.editorMode_layout" ) ,
@@ -458,6 +469,16 @@ export default function Header(props: HeaderProps) {
458469< HeaderProfile user = { user } />
459470) :(
460471< >
472+ { /* Display a hint about who is editing the app */ }
473+ { concurrentAppEditingState && (
474+ < div style = { { display :'flex' , alignItems :'center' , marginRight :'8px' } } >
475+ < Avatar size = "small" src = { user . avatarUrl } />
476+ < span style = { { marginLeft :'8px' , fontSize :'12px' , color :'#b8b9bf' } } >
477+ { `${ user . username } is currently editing this app.` }
478+ </ span >
479+ </ div >
480+ ) }
481+
461482{ applicationId && (
462483< AppPermissionDialog
463484applicationId = { applicationId }
@@ -472,10 +493,11 @@ export default function Header(props: HeaderProps) {
472493{ SHARE_TITLE }
473494</ GrayBtn >
474495) }
496+
475497< PreviewBtn buttonType = "primary" onClick = { ( ) => preview ( applicationId ) } >
476498{ trans ( "header.preview" ) }
477499</ PreviewBtn >
478-
500+
479501< Dropdown
480502className = "cypress-header-dropdown"
481503placement = "bottomRight"
@@ -484,6 +506,7 @@ export default function Header(props: HeaderProps) {
484506< DropdownMenuStyled
485507style = { { minWidth :"110px" , borderRadius :"4px" } }
486508onClick = { ( e ) => {
509+ if ( concurrentAppEditingState ) return ; // Prevent clicks if the app is being edited by someone else
487510if ( e . key === "deploy" ) {
488511dispatch ( publishApplication ( { applicationId} ) ) ;
489512} else if ( e . key === "snapshot" ) {
@@ -494,24 +517,36 @@ export default function Header(props: HeaderProps) {
494517{
495518key :"deploy" ,
496519label :(
497- < CommonTextLabel > { trans ( "header.deploy" ) } </ CommonTextLabel >
520+ < div style = { { display :'flex' , alignItems :'center' } } >
521+ { concurrentAppEditingState && < LockOutlined style = { { marginRight :'8px' } } /> }
522+ < CommonTextLabel style = { { color :concurrentAppEditingState ?"#ccc" :"#222" } } >
523+ { trans ( "header.deploy" ) }
524+ </ CommonTextLabel >
525+ </ div >
498526) ,
527+ disabled :concurrentAppEditingState ,
499528} ,
500529{
501530key :"snapshot" ,
502531label :(
503- < CommonTextLabel > { trans ( "header.snapshot" ) } </ CommonTextLabel >
532+ < div style = { { display :'flex' , alignItems :'center' } } >
533+ { concurrentAppEditingState && < LockOutlined style = { { marginRight :'8px' } } /> }
534+ < CommonTextLabel style = { { color :concurrentAppEditingState ?"#ccc" :"#222" } } >
535+ { trans ( "header.snapshot" ) }
536+ </ CommonTextLabel >
537+ </ div >
504538) ,
539+ disabled :concurrentAppEditingState ,
505540} ,
506541] }
507542/>
508543) }
509544>
510- < PackUpBtn buttonType = "primary" >
545+ < PackUpBtn buttonType = "primary" disabled = { concurrentAppEditingState } >
511546< PackUpIcon />
512547</ PackUpBtn >
513548</ Dropdown >
514-
549+
515550< HeaderProfile user = { user } />
516551</ >
517552) ;
@@ -520,6 +555,7 @@ export default function Header(props: HeaderProps) {
520555showAppSnapshot ,
521556applicationId ,
522557permissionDialogVisible ,
558+ concurrentAppEditingState , // Include the state in the dependency array
523559] ) ;
524560
525561return (