Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added delete button to select compiled contracts #269

Merged
merged 12 commits into from
Oct 8, 2024
Merged
79 changes: 57 additions & 22 deletions plugin/src/components/CompiledContracts/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,38 @@ import {
import { useAtom } from 'jotai'
import { compiledContractsAtom, selectedCompiledContract } from '../../atoms/compiledContracts'
import * as Select from '../../components/ui_components/Select'
import { ChevronDownIcon } from 'lucide-react'
import { ChevronDownIcon, TrashIcon } from 'lucide-react'

interface CompiledContractsProps {
show: 'class' | 'contract'
}

const CompiledContracts: React.FC<CompiledContractsProps> = (props) => {
const [contracts] = useAtom(compiledContractsAtom)
const CompiledContracts: React.FC<CompiledContractsProps> = (props): JSX.Element => {
const [contracts, setContracts] = useAtom(compiledContractsAtom)
const [selectedContract, setSelectedContract] = useAtom(selectedCompiledContract)

const [selectedContractIdx, setSelectedContractIdx] = useState('0')

const handleCompiledContractSelectionChange = (value: string): void => {
console.log('handleCompiledContractSelectionChange', value)
setSelectedContract(contracts[value as unknown as number])
setSelectedContract(contracts[parseInt(value)])
setSelectedContractIdx(value)
}

const handleDeleteContract = (event: React.MouseEvent<HTMLButtonElement>, index: number): void => {
event.stopPropagation()
setContracts((prevContracts) => prevContracts.filter((_, i) => i !== index))

if (contracts.length === 0) {
setSelectedContract(null)
} else {
setSelectedContract(contracts[0])
setSelectedContractIdx('0')
}
}

if (contracts.length === 0) return <></>

return (
<Select.Root value={selectedContractIdx} onValueChange={(value) => { handleCompiledContractSelectionChange(value) }}>
<Select.Trigger className="flex justify-between select-trigger-deployment">
Expand All @@ -34,29 +48,50 @@ const CompiledContracts: React.FC<CompiledContractsProps> = (props) => {
4
)})`
: 'Contract is not selected'}/>
<Select.Icon>
<ChevronDownIcon />
</Select.Icon>
</Select.Trigger>
<Select.Portal>
<Select.Content>
<Select.Viewport>
{contracts.map((contract, index) => (
<Select.Item value={index.toString()} key={index}>
<Select.ItemText>
{`${getContractNameFromFullName(contract.name)} (${getShortenedHash(
<Select.Icon>
<ChevronDownIcon />
</Select.Icon>
</Select.Trigger>
<Select.Portal>
<Select.Content>
<Select.Viewport>
{contracts.map((contract, index) => (
<SelectItemWithDelete
key={index}
value={index.toString()}
onDelete={handleDeleteContract}
index={index}
isSelected={selectedContract?.classHash === contract.classHash}
>
{`${getContractNameFromFullName(contract.name)} (${getShortenedHash(
contract.classHash ?? '',
6,
4
)})`}
</Select.ItemText>
</Select.Item>
))}
</Select.Viewport>
</Select.Content>
</Select.Portal>
</Select.Root>
</SelectItemWithDelete>
))}
</Select.Viewport>
</Select.Content>
</Select.Portal>
</Select.Root>
)
}

const SelectItemWithDelete = React.forwardRef(
({ children, onDelete, index, value, ...props }: any, ref: React.Ref<HTMLDivElement>): JSX.Element => (
<div className="SelectItemWithDelete">
<Select.Item {...props} ref={ref} value={value} className="w-full">
<Select.ItemText>{children}</Select.ItemText>
</Select.Item>

<button onClick={(event) => onDelete(event, index)} className={'ml-2 p-1 rounded deleteButton'}>
<TrashIcon size={16} />
</button>

</div>
)
)

SelectItemWithDelete.displayName = 'SelectItemWithDelete'

export default CompiledContracts
16 changes: 16 additions & 0 deletions plugin/src/components/ui_components/Select/select.css
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,29 @@ button {
user-select: none;
outline: none;
background: var(--bgPrimary);
border: 1px solid var(--bgPrimary);
}

.SelectItem:hover,
.SelectItem[data-highlighted] {
border: 1px solid var(--secondary);
}

.SelectItemWithDelete {
display: flex;
align-items: center;
justify-content: space-between;
position: relative;
background: var(--bgPrimary);
color: var(--text);
border: 1px solid var(--bgPrimary);
}

.SelectItemWithDelete .deleteButton:hover{
border: 1px solid var(--secondary);
}


/* Keyframe animations */
@keyframes fadeInScaleUp {
from {
Expand Down
197 changes: 94 additions & 103 deletions plugin/src/features/Deployment/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -534,125 +534,116 @@ const Deployment: React.FC<DeploymentProps> = ({ setActiveTab }) => {
return (
<>
<Container>
{contracts.length > 0 && selectedContract != null
? (
<div className="">
<div
className={
'compilation-info flex-col text-center align-items-center mb-2'
}
>
<div className={'icon'}>
<img src={useIcon('deploy-icon.svg')} alt={'deploy-icon'} />
</div>
<span className={'mt-1 mb-1'}>Deploy your selected contract</span>
<div className="">
<div className="compilation-info flex-col text-center align-items-center mb-2">
<div className="icon">
<img src={useIcon('deploy-icon.svg')} alt="deploy-icon" />
</div>
<CompiledContracts show={'class'} />
<button
className="btn btn-warning btn-block d-block w-100 text-break remixui_disabled mb-1 mt-3 px-0 rounded"
style={{
cursor: `${
<span className="mt-1 mb-1 text-no-break">{contracts.length > 0 && selectedContract !== null ? 'Deploy your selected contract' : 'No contracts ready for deployment yet, compile a cairo contract'}</span>
</div>
<CompiledContracts show={'class'} />

{contracts.length > 0 && selectedContract !== null
? (
<div>
<button
className="btn btn-warning btn-block d-block w-100 text-break remixui_disabled mb-1 mt-3 px-0 rounded"
style={{
cursor: `${
isDeclaring ||
account == null ||
selectedContract.declaredInfo.some(
(info) => info.chainId === chainId && info.env === env
)
? 'not-allowed'
: 'pointer'
}`
}}
disabled={
isDeclaring ||
account == null ||
selectedContract.declaredInfo.some(
(info) => info.chainId === chainId && info.env === env
)
? 'not-allowed'
: 'pointer'
}`
}}
disabled={
isDeclaring ||
account == null ||
selectedContract.declaredInfo.some(
(info) => info.chainId === chainId && info.env === env
)
}
aria-disabled={
isDeclaring ||
account == null ||
selectedContract.declaredInfo.some(
(info) => info.chainId === chainId && info.env === env
)
}
onClick={handleDeclare}
>
<div className="d-flex align-items-center justify-content-center">
<div className="text-truncate overflow-hidden text-nowrap">
{isDeclaring
? (
}
aria-disabled={
isDeclaring ||
account == null ||
selectedContract.declaredInfo.some(
(info) => info.chainId === chainId && info.env === env
)
}
onClick={handleDeclare}
>
<div className="d-flex align-items-center justify-content-center">
<div className="text-truncate overflow-hidden text-nowrap">
{isDeclaring
? (
<>
<span style={{ paddingLeft: '0.5rem' }}>
{DeclareStatusLabels[declStatus]}
</span>
</>
)
: (
<div className="text-truncate overflow-hidden text-nowrap">
{account !== null &&
selectedContract.declaredInfo.some(
(info) => info.chainId === chainId && info.env === env
)
? (
<span>
)
: (
<div className="text-truncate overflow-hidden text-nowrap">
{account !== null &&
selectedContract.declaredInfo.some(
(info) => info.chainId === chainId && info.env === env
)
? (
<span>
{' '}
Declared {selectedContract.name}{' '}
<i className="bi bi-check"></i>
</span>
)
: (
<span> Declare {selectedContract.name}</span>
)}
</div>
)}
Declared {selectedContract.name}{' '}
<i className="bi bi-check"></i>
</span>
)
: (
<span> Declare {selectedContract.name}</span>
)}
</div>
)}
</div>
</div>
</div>
</button>
<ConstructorForm
abi={selectedContract.abi}
callBackFn={handleDeploySubmit}
/>
{account != null &&
selectedContract.deployedInfo.some(
(info) =>
info.address === account.address && info.chainId === chainId
) && (
<div className="mt-3">
<label style={{ display: 'block' }}>
Contract deployed! See{' '}
<a
href="/"
className="text-info"
onClick={(e) => {
e.preventDefault()
setActiveTab('interaction')
}}
>
Interact
</a>{' '}
for more!
</label>
</div>
)}
{notEnoughInputs && (
<label>Please fill out all constructor fields!</label>
)}
</div>
)
: (
<NoContractReadyView />
)}
</button>
<ConstructorForm
abi={selectedContract.abi}
callBackFn={handleDeploySubmit}
/>
{account != null &&
selectedContract.deployedInfo.some(
(info) =>
info.address === account.address && info.chainId === chainId
) && (
<div className="mt-3">
<label style={{ display: 'block' }}>
Contract deployed! See{' '}
<a
href="/"
className="text-info"
onClick={(e) => {
e.preventDefault()
setActiveTab('interaction')
}}
>
Interact
</a>{' '}
for more!
</label>
</div>
)}
{notEnoughInputs && (
<label>Please fill out all constructor fields!</label>
)}
</div>
)
: (
<></>
)}
</div>
</Container>
</>
)
}

const NoContractReadyView = (): JSX.Element => (
<div className={'flex flex-column justify-content-center align-items-center'}>
<div className={'icon mb-2'}>
<img src={useIcon('deploy-icon.svg')} alt={'deploy-icon'} />
</div>
<p>No contracts ready for deployment yet, compile a cairo contract</p>
</div>
)
export default Deployment
Loading