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

[explorer] Adds Search Filter #1959

Merged
merged 7 commits into from
May 13, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions explorer/client/\
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
.form {
@apply flex;
}

.searchbtn {
@apply bg-sui hover:bg-suidark hover:text-white
border-none text-black rounded-r-md
cursor-pointer font-sans
leading-8 flex-initial mr-[1vw] sm:mr-[5vw] ml-0;
}

.disabled {
@apply bg-offblack hover:bg-offblack text-white cursor-text;
}

.searchtext {
@apply border-none rounded-l-md font-mono leading-8 ml-0
flex-1 ml-[1vw] sm:ml-[5vw] w-[5rem]
text-xs mr-0 bg-offwhite;
}

.categoryDropdown, .categoryDropdown > option {
@apply flex-initial font-sans cursor-pointer rounded-none border-none border-l-2 border-black;
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,3 @@
.noobjects {
@apply font-sans tracking-tight font-semibold
bg-amber-300 rounded-l-md
h-[1.5rem] p-2 mt-2;
}

.ownedobjects {
@apply w-[100%] lg:flex lg:flex-wrap lg:justify-between;
}
Expand Down Expand Up @@ -70,5 +64,9 @@ button.btncontainer {
}

.gray {
color: gray;
@apply text-slate-500;
}

.fail {
@apply text-red-600 font-sans font-semibold mt-2;
}
88 changes: 47 additions & 41 deletions explorer/client/src/components/ownedobjects/OwnedObjects.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ const IS_COIN_TYPE = (typeDesc: string): boolean => /::Coin::/.test(typeDesc);
const lastRowHas2Elements = (itemList: any[]): boolean =>
itemList.length % 3 === 2;

const NoOwnedObjects = () => (
<div className={styles.fail}>Failed to find Owned Objects</div>
);

const OwnedObject = ({ id }: { id: string }) =>
IS_STATIC_ENV ? <OwnedObjectStatic id={id} /> : <OwnedObjectAPI id={id} />;

Expand All @@ -62,61 +66,63 @@ function OwnedObjectStatic({ id }: { id: string }) {

return <OwnedObjectLayout results={results} />;
} else {
return <div />;
return <NoOwnedObjects />;
}
}

function OwnedObjectAPI({ id }: { id: string }) {
const [results, setResults] = useState(DATATYPE_DEFAULT);
const [isLoaded, setIsLoaded] = useState(false);
const [isFail, setIsFail] = useState(false);

// TODO - The below will fail for a large number of owned objects
// due to the number of calls to the API
// Backend changes will be required to enable a scalable solution
// getOwnedObjectRefs will need to return id, type and balance for each owned object
useEffect(() => {
rpc.getOwnedObjectRefs(id).then((objects) => {
const ids = objects.map(({ objectId }) => objectId);
rpc.getObjectInfoBatch(ids).then((results) => {
setResults(
results
.filter(({ status }) => status === 'Exists')
.map(
(resp) => {
const info = getObjectExistsResponse(resp)!;
const contents = getObjectContent(resp);
const url = parseImageURL(info.object);
const balanceValue = (
typeof contents?.fields.balance === 'number'
? contents.fields.balance
: undefined
) as number;
return {
id: info.objectRef.objectId,
Type: parseObjectType(info),
display: url
? processDisplayValue(url)
: undefined,
balance: balanceValue,
};
}
//TO DO - add back version
)
);
setIsLoaded(true);
});
});
setIsFail(false);
setIsLoaded(false);
rpc.getOwnedObjectRefs(id)
.then((objects) => {
const ids = objects.map(({ objectId }) => objectId);
rpc.getObjectInfoBatch(ids).then((results) => {
setResults(
results
.filter(({ status }) => status === 'Exists')
.map(
(resp) => {
const info = getObjectExistsResponse(resp)!;
const contents = getObjectContent(resp);
const url = parseImageURL(info.object);
const balanceValue = (
typeof contents?.fields.balance ===
'number'
? contents.fields.balance
: undefined
) as number;
return {
id: info.objectRef.objectId,
Type: parseObjectType(info),
display: url
? processDisplayValue(url)
: undefined,
balance: balanceValue,
};
}
//TO DO - add back version
)
);
setIsLoaded(true);
});
})
.catch(() => setIsFail(true));
}, [id]);

if (isLoaded) {
return <OwnedObjectLayout results={results} />;
} else {
return results.length > 0 ? (
<div className={styles.gray}>loading...</div>
) : (
<div />
);
}
if (isFail) return <NoOwnedObjects />;

if (isLoaded) return <OwnedObjectLayout results={results} />;

return <div className={styles.gray}>loading...</div>;
}

function OwnedObjectLayout({ results }: { results: resultType }) {
Expand Down
17 changes: 10 additions & 7 deletions explorer/client/src/components/search/Search.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,23 @@
@apply flex;
}

.searchbtn,
.categorydropdown,
select.categorydropdown > option {
@apply flex-initial font-sans text-xs border-none;
}

.searchbtn {
@apply bg-sui hover:bg-suidark hover:text-white
border-none text-black rounded-r-md
cursor-pointer font-sans
leading-8 flex-initial mr-[5vw] ml-0;
@apply bg-sui hover:bg-suidark hover:text-white rounded-r-md cursor-pointer leading-8 mr-[1vw] sm:mr-[5vw] ml-0;
}

.disabled {
@apply bg-offblack hover:bg-offblack text-white cursor-text;
}

.searchtext {
@apply border-none rounded-l-md font-mono leading-8 flex-1 ml-[5vw]
@apply border-r-2 border-y-0 border-l-0 rounded-l-md
font-mono leading-8
flex-1 ml-[1vw] sm:ml-[5vw] w-[5rem]
text-xs mr-0 bg-offwhite;

padding-left: 0.75rem;
}
47 changes: 42 additions & 5 deletions explorer/client/src/components/search/Search.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,22 @@ import { navigateWithUnknown } from '../../utils/searchUtil';

import styles from './Search.module.css';

type SearchCategory = 'all' | 'transactions' | 'addresses' | 'objects';
function getPlaceholderText(category: SearchCategory) {
switch (category) {
case 'addresses':
return 'Search by address';
case 'transactions':
return 'Search by digest';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return 'Search by digest';
return 'Search by transaction id';

Even though "digest" is technically more accurate, we use TxnId everywhere else, so let's be consistent here
CleanShot 2022-05-13 at 12 18 15

case 'objects':
case 'all':
return 'Search by ID';
}
}

function Search() {
const [input, setInput] = useState('');
const [category, setCategory] = useState('all' as SearchCategory);
const navigate = useNavigate();

const [pleaseWaitMode, setPleaseWaitMode] = useState(false);
Expand All @@ -20,20 +34,33 @@ function Search() {
// Prevent empty search
if (!input.length) return;
setPleaseWaitMode(true);
// remove empty char from input
navigateWithUnknown(input.trim(), navigate).then(() => {

if (category === 'all') {
// remove empty char from input
navigateWithUnknown(input.trim(), navigate).then(() => {
setInput('');
setPleaseWaitMode(false);
});
} else {
navigate(`../${category}/${input.trim()}`);
setInput('');
setPleaseWaitMode(false);
});
setCategory('all');
}
},
[input, navigate, setInput]
[input, navigate, category, setInput]
);

const handleTextChange = useCallback(
(e: React.ChangeEvent<HTMLInputElement>) =>
setInput(e.currentTarget.value),
[setInput]
);
const handleCategoryChange = useCallback(
(e: React.ChangeEvent<HTMLSelectElement>) =>
setCategory(e.currentTarget.value as SearchCategory),
[setCategory]
);

return (
<form
Expand All @@ -44,11 +71,21 @@ function Search() {
<input
className={styles.searchtext}
id="searchText"
placeholder="Search by ID"
placeholder={getPlaceholderText(category)}
value={input}
onChange={handleTextChange}
type="text"
/>
<select
className={styles.categorydropdown}
onChange={handleCategoryChange}
value={category}
>
<option value="all">All</option>
<option value="transactions">Transactions</option>
<option value="objects">Objects</option>
<option value="addresses">Addresses</option>
</select>
<input
type="submit"
id="searchBtn"
Expand Down
2 changes: 1 addition & 1 deletion explorer/client/src/pages/object-result/ObjectResult.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ const Fail = ({ objID }: { objID: string | undefined }): JSX.Element => {
return (
<ErrorResult
id={objID}
errorMsg="There was an issue with the data on the following object"
errorMsg="Data could not be extracted on the following specified object ID"
/>
);
};
Expand Down
38 changes: 22 additions & 16 deletions explorer/client/src/pages/transaction-result/TransactionResult.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,17 @@ const getCreatedOrMutatedData = (
: [];
};

const FailedToGetTxResults = ({ id }: { id: string }) => (
<ErrorResult
id={id}
errorMsg={
!id
? "Can't search for a transaction without a digest"
: 'Data could not be extracted for the following specified transaction ID'
}
/>
);

const transformTransactionResponse = (
txObj: TransactionEffectsResponse,
id: string
Expand Down Expand Up @@ -151,26 +162,21 @@ const TransactionResultAPI = ({ id }: { id: string }) => {
// For Batch transactions show error
// TODO update Error screen and account for Batch transactions

return (
<ErrorResult
id={id}
errorMsg={
!id
? "Can't search for a transaction without a digest"
: 'There was an issue with the data on the following transaction'
}
/>
);
return <FailedToGetTxResults id={id} />;
};

const TransactionResultStatic = ({ id }: { id: string }) => {
const entry = findDataFromID(id, undefined);

return (
<TransactionResultLoaded
txData={transformTransactionResponse(entry, id)}
/>
);
try {
return (
<TransactionResultLoaded
txData={transformTransactionResponse(entry, id)}
/>
);
} catch (error) {
console.error(error);
return <FailedToGetTxResults id={id} />;
}
};

const TransactionResultLoaded = ({ txData }: { txData: DataType }) => {
Expand Down