react-router#useParams JavaScript Examples
The following examples show how to use
react-router#useParams.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: TopicsView.jsx From frontend-app-discussions with GNU Affero General Public License v3.0 | 6 votes |
function LegacyCoursewareTopics() {
const { category } = useParams();
const categories = useSelector(selectCategories)
.filter(cat => (category ? cat === category : true));
return categories?.map(
topicGroup => (
<LegacyTopicGroup
id={topicGroup}
category={topicGroup}
key={topicGroup}
/>
),
);
}
Example #2
Source File: TopicsView.jsx From frontend-app-discussions with GNU Affero General Public License v3.0 | 6 votes |
function CourseWideTopics() {
const { category } = useParams();
const filter = useSelector(selectTopicFilter);
const nonCoursewareTopics = useSelector(selectNonCoursewareTopics);
return (nonCoursewareTopics && category === undefined) && nonCoursewareTopics.filter(
item => (filter
? item.name.toLowerCase()
.includes(filter)
: true
),
)
.map(topic => (
<Topic topic={topic} key={topic.id} />
));
}
Example #3
Source File: EditorContainer.jsx From frontend-app-course-authoring with GNU Affero General Public License v3.0 | 6 votes |
EditorContainer = ({
courseId,
}) => {
const { blockType, blockId } = useParams();
return (
<div className="editor-page">
<EditorPage
courseId={courseId}
blockType={blockType}
blockId={blockId}
studioEndpointUrl={process.env.STUDIO_BASE_URL}
lmsEndpointUrl={process.env.LMS_BASE_URL}
/>
</div>
);
}
Example #4
Source File: promo-code-edit.js From horondi_admin with MIT License | 6 votes |
function PromoCodeEdit() {
const { id } = useParams();
const history = useHistory();
const dispatch = useDispatch();
const { loading, error, data } = useQuery(getPromoCodeById, {
variables: { id },
fetchPolicy: 'no-cache'
});
const onCompletedHandler = () => {
dispatch(showSuccessSnackbar('Успішно змінено'));
};
const [updatePromoCodeHandler] = useMutation(updatePromoCode, {
onCompleted: onCompletedHandler
});
const pathToPromoCodesPage = config.routes.pathToPromoCodes;
const goToPromoPage = () => {
history.push(pathToPromoCodesPage);
};
if (loading || error) {
return <LoadingBar />;
}
return (
<PromoCodeForm
initialState={data.getPromoCodeById}
promoValidationSchema={promoValidationSchema}
pathToPromoCodesPage={pathToPromoCodesPage}
addPromoCodeHandler={updatePromoCodeHandler}
goToPromoPage={goToPromoPage}
/>
);
}
Example #5
Source File: Card.js From berry-hot with The Unlicense | 6 votes |
function CardPage(props) {
const { cardId } = useParams();
return (
<div className="container">
<div className="row">
<div className="col col-12 col-lg-8 col-xl-6">
<Card {...props} cardId={parseInt(cardId)} />
</div>
</div>
</div>
);
}
Example #6
Source File: CreateDeploymentWizard.js From akashlytics-deploy with GNU General Public License v3.0 | 5 votes |
export function CreateDeploymentWizard() {
const classes = useStyles();
const [selectedTemplate, setSelectedTemplate] = useState(null);
const [editedManifest, setEditedManifest] = useState(null);
const { step, dseq } = useParams();
const history = useHistory();
useEffect(() => {
setEditedManifest(selectedTemplate?.content);
}, [selectedTemplate]);
function handleBackClick() {
let route = "";
switch (step) {
case "editManifest":
route = UrlService.createDeploymentStepTemplate();
break;
case "acceptBids":
route = UrlService.createDeploymentStepManifest();
break;
default:
break;
}
if (route) {
history.replace(route);
} else {
history.goBack();
}
}
let activeStep = getStepIndexByParam(step);
function getStepIndexByParam(step) {
switch (step) {
case "chooseTemplate":
return 1;
case "editManifest":
return 2;
case "acceptBids":
return 3;
default:
return 0;
}
}
return (
<div className={classes.root}>
<div className={classes.stepContainer}>
<Box padding="1rem 0 1rem .5rem">
<IconButton aria-label="back" onClick={handleBackClick} size="medium">
<ChevronLeftIcon />
</IconButton>
</Box>
<CustomizedSteppers steps={steps} activeStep={activeStep} />
</div>
<div>
{activeStep === 0 && <PrerequisiteList selectedTemplate={selectedTemplate} setSelectedTemplate={(c) => setSelectedTemplate(c)} />}
{activeStep === 1 && <TemplateList selectedTemplate={selectedTemplate} setSelectedTemplate={(c) => setSelectedTemplate(c)} />}
{activeStep === 2 && <ManifestEdit selectedTemplate={selectedTemplate} editedManifest={editedManifest} setEditedManifest={setEditedManifest} />}
{activeStep === 3 && <CreateLease dseq={dseq} editedManifest={editedManifest} />}
</div>
</div>
);
}
Example #7
Source File: SalePage.js From app-ui with The Unlicense | 5 votes |
function SalePage(props) {
let { saleId } = useParams();
const sales = useSales();
saleId = parseInt(saleId);
const sale = sales.sales[saleId];
const currentReferralId = getCurrentReferralId(saleId);
const [referralId, setReferralId] = useState(currentReferralId);
const location = useLocation();
const history = useHistory();
const account = useAccount();
const locationSearch = location.search;
const query = new URLSearchParams(locationSearch);
const r = query.get("r");
if (r) {
setReferralId(r);
query.delete("r");
location.search = query.toString();
history.replace(location);
}
if (account && !account.loading && referralId !== currentReferralId) {
if (!account.accountId || account.accountId !== referralId) {
console.log("New referral", referralId);
ls.set(referralLsKey(saleId), {
referralId,
expires: new Date().getTime() + 7 * 24 * 60 * 60 * 1000,
});
}
}
return (
<div>
<div className="container">
<div className="row justify-content-md-center mb-3">
{sales.loading ? (
"Loading"
) : sale ? (
<Sale sale={sale} />
) : (
"Sale not found"
)}
</div>
</div>
</div>
);
}
Example #8
Source File: index.js From dstack-server with Apache License 2.0 | 5 votes |
Item = ({
withLink,
onClick,
data,
deleteAction,
userData,
}: Props) => {
const params = useParams();
const {t} = useTranslation();
const ref = useRef(null);
const Component = withLink ? Link : 'div';
return (
<Component
className={css.item}
ref={ref}
onClick={onClick}
{...(withLink ? {to: routes.stackDetails(data.user, data.name)} : {})}
>
<div className={css.previewWrap}>
{data.head
? <Attachment
className={css.attachment}
isList
withLoader
stack={`${data.user}/${data.name}`}
frameId={data.head}
id={0}
/>
: <div className={css.emptyMessage}>{t('emptyStack')}</div>
}
</div>
<div className={css.section}>
<div className={css.content}>
<div className={css.name}>
{data.name}
{' '}
<span className={`mdi mdi-lock${data.private ? '' : '-open'}`} />
</div>
{params.user !== data.user && (
<div className={css.by}>{t('by')} {data.user}</div>
)}
</div>
{deleteAction && get(userData, 'user') === data.user && (
<Dropdown
className={css.dropdown}
items={[
// {
// title: t('rename'),
// onClick: () => {},
// },
{
title: t('delete'),
onClick: () => deleteAction(data.name),
},
]}
/>
)}
</div>
</Component>
);
}
Example #9
Source File: Topic.jsx From frontend-app-discussions with GNU Affero General Public License v3.0 | 5 votes |
function Topic({ topic }) {
const { courseId } = useParams();
const topicUrl = discussionsPath(Routes.TOPICS.TOPIC, {
courseId,
topicId: topic.id,
});
const icons = [
{
key: 'discussions',
icon: PostOutline,
count: topic.threadCounts?.discussion || 0,
},
{
key: 'questions',
icon: Help,
count: topic.threadCounts?.question || 0,
},
];
return (
<Link
className="discussion-topic d-flex flex-column list-group-item px-4 py-3 text-primary-500"
data-topic-id={topic.id}
to={topicUrl}
>
<div className="topic-name">
{topic.name}
</div>
<div className="d-flex mt-3">
{
icons.map(({
key,
icon,
count,
}) => (
<div className="mr-4 d-flex align-items-center" key={key}>
<Icon className="mr-2" src={icon} />
{/* Reserve some space for larger counts */}
<span>
{count}
</span>
</div>
))
}
{topic?.flags && (
<div className="d-flex align-items-center">
<Icon className="mr-2" src={ErrorIcon} />
{topic.flags}
</div>
)}
</div>
</Link>
);
}
Example #10
Source File: NavigationBar.jsx From frontend-app-discussions with GNU Affero General Public License v3.0 | 5 votes |
function NavigationBar({ intl }) {
const { courseId } = useParams();
const learnersTabEnabled = useSelector(selectLearnersTabEnabled);
const navLinks = [
{
route: Routes.POSTS.MY_POSTS,
labelMessage: messages.myPosts,
},
{
route: Routes.POSTS.ALL_POSTS,
labelMessage: messages.allPosts,
},
{
route: Routes.TOPICS.ALL,
isActive: (match, location) => Boolean(matchPath(location.pathname, { path: Routes.TOPICS.PATH })),
labelMessage: messages.allTopics,
},
];
if (learnersTabEnabled) {
navLinks.push({
route: Routes.LEARNERS.PATH,
labelMessage: messages.learners,
});
}
return (
<Nav variant="pills" className="py-2">
{navLinks.map(link => (
<Nav.Item key={link.route}>
<Nav.Link
as={NavLink}
to={discussionsPath(link.route, { courseId })}
className="border"
isActive={link.isActive}
>
{intl.formatMessage(link.labelMessage)}
</Nav.Link>
</Nav.Item>
))}
</Nav>
);
}
Example #11
Source File: LearnersView.jsx From frontend-app-discussions with GNU Affero General Public License v3.0 | 5 votes |
function LearnersView({ intl }) {
const { courseId } = useParams();
const location = useLocation();
const dispatch = useDispatch();
const orderBy = useSelector(selectLearnerSorting());
const nextPage = useSelector(selectLearnerNextPage());
const loadingStatus = useSelector(learnersLoadingStatus());
const courseConfigLoadingStatus = useSelector(selectconfigLoadingStatus);
const learnersTabEnabled = useSelector(selectLearnersTabEnabled);
const learners = useSelector(selectAllLearners);
useEffect(() => {
if (learnersTabEnabled) {
dispatch(fetchLearners(courseId, { orderBy }));
}
}, [courseId, orderBy, learnersTabEnabled]);
const loadPage = async () => {
if (nextPage) {
dispatch(fetchLearners(courseId, {
orderBy,
page: nextPage,
}));
}
};
return (
<div className="d-flex flex-column border-right border-light-300 h-100">
<LearnerFilterBar />
<div className="list-group list-group-flush learner">
{courseConfigLoadingStatus === RequestStatus.SUCCESSFUL && !learnersTabEnabled && (
<Redirect
to={{
...location,
pathname: Routes.DISCUSSIONS.PATH,
}}
/>
)}
{courseConfigLoadingStatus === RequestStatus.SUCCESSFUL && learnersTabEnabled && learners.map((learner) => (
<LearnerCard learner={learner} key={learner.username} courseId={courseId} />
))}
{loadingStatus === RequestStatus.IN_PROGRESS ? (
<div className="d-flex justify-content-center p-4">
<Spinner animation="border" variant="primary" size="lg" />
</div>
) : (
nextPage && loadingStatus === RequestStatus.SUCCESSFUL && (
<Button onClick={() => loadPage()} variant="primary" size="md">
{intl.formatMessage(messages.loadMore)}
</Button>
)
)}
</div>
</div>
);
}
Example #12
Source File: CommentsView.jsx From frontend-app-discussions with GNU Affero General Public License v3.0 | 5 votes |
function CommentsView({ intl }) {
const { postId } = useParams();
const thread = usePost(postId);
if (!thread) {
return (
<Spinner animation="border" variant="primary" data-testid="loading-indicator" />
);
}
return (
<>
<div className="discussion-comments d-flex flex-column mt-3 mb-0 mx-3 p-4 card">
<Post post={thread} />
<ResponseEditor postId={postId} />
</div>
{thread.type === ThreadType.DISCUSSION
&& (
<DiscussionCommentsView
postId={postId}
intl={intl}
postType={thread.type}
endorsed={EndorsementStatus.DISCUSSION}
/>
)}
{thread.type === ThreadType.QUESTION && (
<>
<DiscussionCommentsView
postId={postId}
intl={intl}
postType={thread.type}
endorsed={EndorsementStatus.ENDORSED}
/>
<DiscussionCommentsView
postId={postId}
intl={intl}
postType={thread.type}
endorsed={EndorsementStatus.UNENDORSED}
/>
</>
)}
</>
);
}
Example #13
Source File: TinyMCEEditor.jsx From frontend-app-discussions with GNU Affero General Public License v3.0 | 5 votes |
/* istanbul ignore next */
export default function TinyMCEEditor(props) {
// note that skin and content_css is disabled to avoid the normal
// loading process and is instead loaded as a string via content_style
const { courseId, postId } = useParams();
const uploadHandler = async (blobInfo, success, failure) => {
try {
const blob = blobInfo.blob();
const filename = blobInfo.filename();
const { location } = await uploadFile(blob, filename, courseId, postId || 'root');
success(location);
} catch (e) {
failure(e.toString(), { remove: true });
}
};
let contentStyle;
// In the test environment this causes an error so set styles to empty since they aren't needed for testing.
try {
contentStyle = [contentCss, contentUiCss, edxBrandCss].join('\n');
} catch (err) {
contentStyle = '';
}
return (
<Editor
init={{
skin: false,
menubar: false,
branding: false,
contextmenu: false,
browser_spellcheck: true,
a11y_advanced_options: true,
autosave_interval: '1s',
autosave_restore_when_empty: true,
plugins: 'autosave codesample link lists image imagetools code emoticons charmap',
toolbar: 'formatselect | bold italic underline'
+ ' | link blockquote openedx_code image'
+ ' | bullist numlist outdent indent'
+ ' | removeformat'
+ ' | openedx_html'
+ ' | undo redo'
+ ' | emoticons'
+ ' | charmap',
content_css: false,
content_style: contentStyle,
body_class: 'm-2 text-editor',
default_link_target: '_blank',
target_list: false,
images_upload_handler: uploadHandler,
setup,
}}
{...props}
/>
);
}
Example #14
Source File: Account.js From berry-hot with The Unlicense | 5 votes |
function AccountPage(props) {
const { accountId } = useParams();
const [account, setAccount] = useState(null);
const [loading, setLoading] = useState(true);
const [cardIds, setCardsIds] = useState([]);
const [gkey] = useState(uuid());
const fetchCards = useCallback(async () => {
const account = await props._near.getAccount(accountId);
if (!account) {
return;
}
setAccount(account);
return await account.fetchCards();
}, [props._near, accountId])
useEffect(() => {
if (props.connected) {
fetchCards().then((cardIds) => {
cardIds.sort((a, b) => b[1] - a[1]);
setCardsIds(cardIds);
setLoading(false);
})
}
}, [props.connected, fetchCards])
const cards = cardIds.map(([cardId, rating]) => {
const key = `${gkey}-${cardId}`;
return (
<CardPreview {...props} key={key} cardId={cardId} rating={rating} />
);
})
return (
<div className="container">
<div className="row justify-content-md-center">
{loading ? (
<div className="col">
<div className="d-flex justify-content-center">
<div className="spinner-grow" role="status">
<span className="visually-hidden">Loading...</span>
</div>
</div>
</div>
) : (
<div className="col ">
<h3>{accountId === props.signedAccountId ? "Your cards" : `Cards owned by @${accountId}`}</h3>
<div>
{cards}
</div>
</div>
)}
{!account ? (
<div className="col col-12 col-lg-8 col-xl-6">
<div className="d-flex justify-content-center">
<div className="spinner-grow" role="status">
<span className="visually-hidden">Loading...</span>
</div>
</div>
</div>
) : (
<div className="col col-12 col-lg-4 col-xl-4">
<h3>Stats</h3>
<ul>
<li>Num cards: {account.numCards}</li>
<li>Purchase volume: {account.purchaseVolume.toFixed(2)} NEAR</li>
<li>Num purchases: {account.numPurchases}</li>
<li>Sale profit: {account.saleProfit.toFixed(2)} NEAR</li>
<li>Num sales: {account.numSales}</li>
<li>Num votes: {account.numVotes}</li>
</ul>
</div>
)}
</div>
</div>
);
}
Example #15
Source File: TemplateDetails.js From akashlytics-deploy with GNU General Public License v3.0 | 5 votes |
export function TemplateDetails() {
const [activeTab, setActiveTab] = useState("README");
const { templateId } = useParams();
const { getTemplateById } = useTemplates();
const history = useHistory();
const classes = useStyles();
const template = getTemplateById(templateId);
function handleBackClick() {
history.goBack();
}
function handleOpenGithub() {
window.electron.openUrl(template.githubUrl);
}
return (
<div className={classes.root}>
<Helmet title="Deployment Detail" />
<div className={classes.titleContainer}>
<Box display="flex" alignItems="center">
<IconButton aria-label="back" onClick={handleBackClick}>
<ChevronLeftIcon />
</IconButton>
<Typography variant="h3" className={classes.title}>
{template.name}
</Typography>
<Box marginLeft="1rem">
<IconButton aria-label="View on github" title="View on Github" onClick={handleOpenGithub} size="small">
<GitHubIcon fontSize="small" />
</IconButton>
</Box>
</Box>
<Button
className={classes.deployBtn}
variant="contained"
size="medium"
color="primary"
component={Link}
to={UrlService.createDeploymentFromTemplate(template.id)}
>
<PublishIcon />
Deploy
</Button>
</div>
<Tabs value={activeTab} onChange={(ev, value) => setActiveTab(value)} indicatorColor="primary" textColor="primary">
<Tab value="README" label="README" />
<Tab value="SDL" label="SDL" />
{template.guide && <Tab value="GUIDE" label="GUIDE" />}
</Tabs>
{activeTab === "README" && (
<ViewPanel bottomElementId="footer" overflow="auto" padding="1rem">
<ReactMarkdown linkTarget="_blank" remarkPlugins={[remarkGfm]} className="markdownContainer">
{template.readme}
</ReactMarkdown>
</ViewPanel>
)}
{activeTab === "SDL" && (
<ViewPanel bottomElementId="footer" overflow="hidden">
<MonacoEditor height="100%" language="yaml" theme="vs-dark" value={template.deploy} options={{ ...monacoOptions, readOnly: true }} />
</ViewPanel>
)}
{activeTab === "GUIDE" && (
<ViewPanel bottomElementId="footer" overflow="auto" padding="1rem">
<ReactMarkdown linkTarget="_blank" remarkPlugins={[remarkGfm]} className="markdownContainer">
{template.guide}
</ReactMarkdown>
</ViewPanel>
)}
</div>
);
}
Example #16
Source File: Facility.js From dashboard with MIT License | 5 votes |
function Facility() {
const params = useParams();
const facility = params.facilityId;
// const date = Date.parse(query.get("date"));
const date = new Date();
const [patientData, setPatientData] = useState({});
const [facilityData, setFacilityData] = useState({});
const [patientLoading, setPatientLoading] = useState(true);
const [facilityLoading, setFacilityLoading] = useState(true);
const [oxygenData, setOxygen] = useState({});
const patientsFiltered =
patientData.results &&
processFacilities(patientData.results, FACILITY_TYPES);
const filtered =
facilityData.results &&
processFacilities(facilityData.results, FACILITY_TYPES);
const todayFiltered =
filtered && filtered.filter((f) => f.date === dateString(date));
useEffect(() => {
individualCareSummary(
"patient",
dateString(getNDateBefore(date, 1)),
dateString(getNDateAfter(date, 1)),
facility
).then((data) => {
setPatientData(data);
setPatientLoading(false);
});
individualCareSummary(
"facility",
dateString(getNDateBefore(date, 1)),
dateString(getNDateAfter(date, 1)),
facility
).then((data) => {
setFacilityData(data);
setOxygen(data.results[0]?.data?.inventory || {});
setFacilityLoading(false);
});
}, []);
return (
!facilityLoading &&
!patientLoading && (
<div className="h-fulle w-full dark:text-white">
<FacilityInfo facilityData={facilityData} />
<Capacity filtered={filtered} date={date} />
<Patients patientsFiltered={patientsFiltered} date={date} />
<Oxygen oxygenData={oxygenData} />
<ExpectedBurnRate patientData={patientData} />
<section className="my-8 px-6 py-4 dark:bg-gray-700 bg-white">
<h2 className="text-primary-500 text-lg font-bold">Map</h2>
<GMap
className="mb-8 mt-6"
facilities={todayFiltered}
district={ACTIVATED_DISTRICTS[0]}
/>
</section>
</div>
)
);
}
Example #17
Source File: LeaderBoard.js From Website with MIT License | 5 votes |
LeaderBoard = ({ history }) => {
const [leaderBoardInfo, setLeaderBoardInfo] = useState([]);
const [guildInfo, setGuildInfo] = useState({});
const { id } = useParams();
const [fullLoading, setFullLoading] = useState(true);
const [page, setPage] = useState(1);
const [pageSize, ] = useQueryParam("page-size", NumberParam);
const { items, isLoading: loading, isStart, isEnd, getPrev, getNext } = usePagination(
firebase.db.collection("Leveling").doc(id).collection("users").orderBy("xp", "desc"),
{ limit: pageSize || defaultPageSize }
);
useEffect(() => {
setTimeout(() => {
window.scrollTo(0, 0);
}, 100);
(async () => {
setFullLoading(true);
if (loading) return;
const leaderBoardDashBoard = items;
setFullLoading(loading);
setLeaderBoardInfo(items.filter(item => item.name));
try {
const guildResponse = await fetch(`${process.env.REACT_APP_API_URL}/resolveguild?guild=${id}`);
const guildJson = await guildResponse.json();
setGuildInfo(prev => guildJson || prev);
} catch (err) {}
})();
}, [id, items, loading, history, pageSize]);
return (
<div className="leaderboard">
<SmallLoader loaded={!fullLoading} />
<div className="leaderboard-header">
<img src={guildInfo.iconURL} alt="" />
<h1>{guildInfo.name}</h1>
</div>
{!fullLoading && (
<div className="leaderboard-body">
<ul>
{leaderBoardInfo.map((user, idx) => (
<LeaderBoardCard guild={id} key={user.name} place={idx + 1 + ((page || 1) - 1) * (pageSize || defaultPageSize)} {...user} />
))}
</ul>
<div className="leaderboard-footer">
{!isStart && (
<button
onClick={() => {
getPrev();
setPage(prev => prev - 1);
}}
>
Previous Page
</button>
)}
{!isEnd && (
<button
onClick={() => {
getNext();
setPage(prev => prev + 1);
}}
>
Next Page
</button>
)}
</div>
</div>
)}
</div>
);
}
Example #18
Source File: index.js From ActiveLearningStudio-react-client with GNU Affero General Public License v3.0 | 4 votes |
MyActivity = ({ playlistPreview }) => {
const [edit, setEdit] = useState(false);
const [addActivityPopUp, setAddActivityPopUp] = useState(false);
const params = useParams();
useEffect(() => {
if (params.statusbool) {
setEdit(params.statusbool);
}
}, []);
const [cardShow, setCardShow] = useState(true);
const [uploadImageStatus, setUploadImageStatus] = useState(false);
const [showFilter, setShowFilter] = useState(false);
const [listView, setListView] = useState(false);
const [activtyMethod, setActivityMethod] = useState('create');
const [activeType, setActiveType] = useState('');
const [currentActivity, setCurrentActivity] = useState(null);
const [modalShow, setModalShow] = useState(false);
const { screenState, activity } = useSelector((state) => state.myactivities);
const dispatch = useDispatch();
const changeScreenHandler = (payload, method) => {
dispatch({
type: actionTypes.SET_ACTIVE_ACTIVITY_SCREEN,
payload: payload,
});
if (method === 'upload') {
setActivityMethod('upload');
} else {
setActivityMethod('create');
}
};
return (
<>
{screenState && (
<div className={uploadImageStatus ? 'form-new-popup-activity z-index' : 'form-new-popup-activity '}>
<div style={{ paddingTop: '100px' }} className="inner-form-content ">
<div className="inner-form-content-box ">
<div className="cross-all-pop-box ">
<FontAwesomeIcon
icon="times"
className="cross-all-pop"
onClick={() => {
Swal.fire({
text: 'All changes will be lost if you don’t save them',
icon: 'warning',
showCancelButton: true,
confirmButtonColor: '#084892',
cancelButtonColor: '#d33',
confirmButtonText: 'Yes, Close it!',
allowOutsideClick: false,
}).then(async (result) => {
if (result.isConfirmed) {
changeScreenHandler('');
}
});
}}
/>
</div>
{/* {screenState === "newactivity" && (
<NewActivity
changeScreenHandler={changeScreenHandler}
screenState={screenState}
/>
)} */}
{screenState === 'layout' && <ActivityLayout changeScreenHandler={changeScreenHandler} screenState={screenState} />}
{screenState === 'addactivity' && (
<AddActivity
setActivityMethod={setActivityMethod}
changeScreenHandler={changeScreenHandler}
screenState={screenState}
activtyMethod={activtyMethod}
setUploadImageStatus={setUploadImageStatus}
/>
)}
{screenState === 'uploadinteractivevideo' && <UploadInteractiveVideo changeScreenHandler={changeScreenHandler} screenState={screenState} />}
{screenState === 'preview' && <PreviewLayout changeScreenHandler={changeScreenHandler} screenState={screenState} />}
{screenState === 'singleActivity' && (
<SingleActivity
setCurrentActivity={setCurrentActivity}
setActiveType={setActiveType}
setModalShow={setModalShow}
changeScreenHandler={changeScreenHandler}
screenState={screenState}
/>
)}
{screenState === 'addvideo' && (
<div className="form-new-popup-myvideo ">
<AddVideo showback={true} changeScreenHandler={changeScreenHandler} />
</div>
)}
{screenState === 'describevideo' && (
<div className="form-new-popup-myvideo ">
<DescribeVideo
playlistPreview={activity ? true : false}
reverseType
showback={true}
changeScreenHandler={changeScreenHandler}
setUploadImageStatus={setUploadImageStatus}
/>
</div>
)}
</div>
</div>
</div>
)}
{!playlistPreview && (
<div className="myactivity">
<div className="content-wrapper">
<div className="inner-content">
<div className="topHeadingBtn">
<div className="topHeading">
<TopHeading description="Nevada Department of Education" image={TopHeadingImage} heading="My Activities" color="#084892" />
</div>
<div className="topBtn">
<Buttons primary={true} text="New Activity" icon={faPlus} width="163px" height="35px" onClick={() => changeScreenHandler('layout')} hover={true} />
</div>
</div>
<div className="topDescription">
<HeadingText text="Create new activities, control, manage and organize them in playlists and projects." color="#515151" />
</div>
<div className="activityTitle">
{edit ? <HeadingTwo text="Select Activies to add to a project or create a new one." color="#285AA5" /> : <HeadingTwo text="Activities" color="#285AA5" />}
</div>
<div className="activityBlocks">
<div className="blockBody">
<div className="blockBody-detail">
<HeadingThree text="How to create Activities" color="#515151" className="mb-20" />
<HeadingText
text="Learn how to create awesome
activities using +50 Activty Types
like Dialog Cards, Interactive Videos
and more..."
color="#515151"
className="mb-13"
/>
<HeadingThree text="Learn" color="#515151" />
</div>
</div>
<div className="blockBody ml-54">
<div className="blockBody-text">
<HeadingText text="How to organize Activities into Projects" color="#515151" className="" />
</div>
</div>
</div>
</div>
</div>
</div>
)}
<MyVerticallyCenteredModal show={modalShow} onHide={() => setModalShow(false)} activity={currentActivity} activeType={activeType} />
</>
);
}
Example #19
Source File: about-us-section-edit-form.js From horondi_admin with MIT License | 4 votes |
AboutUsSectionEditForm = ({ businessPage }) => {
const [businessPageData, setBusinessPageData] = useState(businessPage);
const [upload, setUpload] = useState();
const { id } = useParams();
const styles = useStyles();
const dispatch = useDispatch();
const [updateSection, { loading: updateSectionLoading }] = useMutation(
updateBusinessText,
{
onCompleted: (data) => {
if (data?.updateBusinessText?.message) {
dispatch(showErrorSnackbar(ERROR_BOUNDARY_STATUS));
} else {
setBusinessPageData(data.updateBusinessText);
dispatch(showSuccessSnackbar(SUCCESS_UPDATE_STATUS));
}
},
onError: () => {
dispatch(showErrorSnackbar(ERROR_BOUNDARY_STATUS));
}
}
);
const [deleteImg, { loading: deleteImgLoading }] = useMutation(deleteFiles);
const onSubmit = (onSubmitValues) => {
if (upload) {
const imgNames = getImageNamesFromSection(businessPageData, id);
deleteImg({ variables: { fileNames: imgNames } });
}
const updatedBusinessPage = getBusinessPageWithUpdatedSection(
businessPageData,
onSubmitValues,
id,
upload?.name
);
const files = upload ? [upload] : [];
const variables = setVariablesForUpdatingPage(updatedBusinessPage, files);
updateSection({
variables
});
};
const {
values,
errors,
touched,
handleChange,
handleBlur,
setFieldValue,
submitForm
} = useFormik({
initialValues: getInitialValuesForSectionEditing(businessPageData, id),
validationSchema: sectionValidationSchema,
onSubmit
});
const handleImageLoad = (files) => {
const reader = new FileReader();
reader.onload = (event) => {
setFieldValue(img, event.target.result);
};
reader.readAsDataURL(files[0]);
setUpload(files[0]);
};
const inputOptions = {
errors,
touched,
handleChange,
handleBlur,
values,
inputs: [titleEditInput, textEditInput],
setFieldValue
};
if (updateSectionLoading || deleteImgLoading) {
return <LoadingBar />;
}
return (
<div>
<EditingButtonsPanel
pathBack={pathToAboutUs}
submitForm={submitForm}
values={values}
errors={errors}
/>
<form>
<Grid container spacing={1}>
<Grid item xs={12}>
{languages.map((lang) => (
<LanguagePanel
lang={lang}
inputOptions={inputOptions}
key={lang}
/>
))}
</Grid>
<Grid item xs={12}>
<Typography className={styles.title} variant='h5'>
{img.toUpperCase()}
</Typography>
<Paper className={styles.paper}>
<div className={styles.imageUploadContainer}>
<ImageUploadContainer
handler={handleImageLoad}
src={values.img}
/>
</div>
</Paper>
</Grid>
</Grid>
</form>
</div>
);
}
Example #20
Source File: index.js From dstack-server with Apache License 2.0 | 4 votes |
Upload = ({stack, className, isShow, onClose, refresh, withButton}: Props) => {
const {t} = useTranslation();
const [isShowModal, setIsShowModal] = useState(false);
const [uploading, setUploading] = useState(null);
const [progress, setProgress] = useState(null);
const [file, setFile] = useState(null);
const isDidMount = useRef(true);
const {user} = useParams();
const {form, onChange, formErrors, checkValidForm} = useForm(
{stack: stack || ''},
{stack: ['required', 'no-spaces-stack', 'stack-name']}
);
const runValidation = useDebounce(checkValidForm);
useEffect(() => {
if (!isDidMount.current)
runValidation();
else
isDidMount.current = false;
}, [form.stack]);
useEffect(() => {
if (isShow !== undefined)
setIsShowModal(isShow);
}, [isShow]);
const toggleModal = () => setIsShowModal(!isShowModal);
const closeHandle = () => {
if (onClose)
onClose();
else
setIsShowModal(false);
};
const getErrorsText = fieldName => {
if (formErrors[fieldName] && formErrors[fieldName].length)
return [t(`formErrors.${formErrors[fieldName][0]}`)];
};
const submit = async () => {
setProgress(null);
setUploading(true);
const params = {
type: file.type,
timestamp: Date.now(),
id: uuid(),
stack: `${user}/${form.stack}`,
size: file.size,
};
if (file.size > MB)
params.attachments = [{length: file.size}];
else
params.attachments = [{data: await fileToBaseTo64(file)}];
try {
const {data} = await api.post(config.STACK_PUSH, params);
if (data.attachments && data.attachments.length) {
const [attachment] = data.attachments;
if (attachment['upload_url']) {
await axios.put(attachment['upload_url'], file, {
headers: {'Content-Type': 'application/octet-stream'},
onUploadProgress: progressEvent => {
const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total);
setProgress(percentCompleted);
},
});
}
}
setUploading(false);
closeHandle();
if (refresh)
refresh();
} catch (e) {
closeHandle();
}
};
return (
<Fragment>
{withButton && <Tooltip
overlayContent={t('uploadTooltip')}
>
<Button
className={cx(css.upload, className)}
size="small"
color="secondary"
onClick={toggleModal}
>
{t('upload')}
</Button>
</Tooltip>}
<Modal
title={t('uploadFile')}
isShow={isShowModal}
size="small"
>
<div className={css.content}>
{!stack && (
<Fragment>
<div className={css.subtitle}>{t('theUploadedFileWouldBeSavedAsANewStack')}</div>
<TextField
size="middle"
className={css.field}
name="stack"
onChange={onChange}
value={form.value}
maxLength={30}
placeholder={`${t('stackName')}, ${t('noSpaces')}, ${t('maxSymbol', {count: 30})}`}
errors={getErrorsText('stack')}
/>
</Fragment>
)}
{stack && file && (
<div className={css.subtitle}>{t('theUploadedFileWouldBeSavedAsANewRevisionOfTheStack')}</div>
)}
<FileDragnDrop
className={css.dragndrop}
formats={['.csv', '.png', '.svg', '.jpg']}
onChange={setFile}
loading={uploading}
progressPercent={progress}
/>
</div>
<div className={css.buttons}>
<Button
className={css.button}
variant="contained"
color="primary"
disabled={!file || !form.stack.length || uploading}
onClick={submit}
>
{t('save')}
</Button>
<Button
onClick={closeHandle}
className={css.button}
variant="contained"
color="secondary"
disabled={uploading}
>
{t('cancel')}
</Button>
</div>
</Modal>
</Fragment>
);
}
Example #21
Source File: index.js From dstack-server with Apache License 2.0 | 4 votes |
Details = ({
attachment,
attachmentRequestStatus,
fetchDetails,
fetchFrame,
downloadAttachment,
clearDetails,
update,
data = {},
listData = {},
frame,
frameRequestStatus,
loading,
requestStatus,
currentUser,
}: Props) => {
let parsedAttachmentIndex;
const params = useParams();
const {push} = useHistory();
const location = useLocation();
const searchParams = parseSearch(location.search);
if (searchParams.a)
parsedAttachmentIndex = parseInt(searchParams.a);
const [attachmentIndex, setAttachmentIndex] = useState(parsedAttachmentIndex);
const [selectedFrame, setSelectedFrame] = useState(searchParams.f);
const [headId, setHeadId] = useState(null);
const {t} = useTranslation();
const didMountRef = useRef(false);
const {form, setForm, onChange} = useForm({});
const [fields, setFields] = useState({});
const prevFrame = usePrevious(frame);
const [isShowHowToModal, setIsShowHowToModal] = useState(false);
const [isShowUploadModal, setIsShowUploadModal] = useState(false);
const isFirstChangeSearch = useRef(false);
const showHowToModal = event => {
event.preventDefault();
setIsShowHowToModal(true);
};
const hideHowToModal = () => setIsShowHowToModal(false);
const onClickDownloadAttachment = event => {
event.preventDefault();
downloadAttachment(`${params.user}/${params.stack}`, selectedFrame || headId, attachmentIndex || 0);
};
useEffect(() => {
if (isFirstChangeSearch.current) {
let parsedAttachmentIndex;
if (searchParams.a)
parsedAttachmentIndex = parseInt(searchParams.a);
if (parsedAttachmentIndex !== attachmentIndex)
setAttachmentIndex(parsedAttachmentIndex);
if (searchParams.f !== selectedFrame)
setSelectedFrame(searchParams.f);
} else {
isFirstChangeSearch.current = true;
}
}, [location.search]);
useEffect(() => {
let searchParams = {};
if (attachmentIndex)
searchParams.a = attachmentIndex;
if (selectedFrame && selectedFrame !== headId)
searchParams.f = selectedFrame;
const searchString = Object
.keys(searchParams)
.map(key => `${key}=${searchParams[key]}`)
.join('&');
if (location.search.replace('?', '') !== searchString)
push({search: searchString.length ? `?${searchString}` : ''});
}, [attachmentIndex, selectedFrame, headId]);
const fetchData = () => {
fetchDetails(params.user, params.stack);
};
useEffect(() => {
if (!data.head || !listData || (data.head.id !== listData.head))
fetchData();
return () => clearDetails();
}, []);
const setHeadFrame = frameId => {
update({
stack: `${data.user}/${data.name}`,
noUpdateStore: true,
head: frameId,
}, () => setHeadId(frameId));
};
useEffect(() => {
if (selectedFrame)
fetchFrame(params.user, params.stack, selectedFrame);
}, [selectedFrame]);
useEffect(() => {
if ((!isEqual(prevFrame, frame) || !didMountRef.current) && frame)
parseParams();
}, [frame]);
useEffect(() => {
if (data && data.head)
setHeadId(data.head.id);
}, [data]);
const onChangeFrame = frameId => {
setSelectedFrame(frameId);
setAttachmentIndex(undefined);
};
const findAttach = (form, attachmentIndex) => {
const attachments = get(frame, 'attachments');
const fields = Object.keys(form);
if (!attachments)
return;
if (fields.length) {
attachments.some((attach, index) => {
let valid = true;
fields.forEach(key => {
if (!attach.params || !isEqual(attach.params[key], form[key]))
valid = false;
});
if (valid && !(attachmentIndex === undefined && index === 0))
setAttachmentIndex(index);
return valid;
});
}
};
const findAttachDebounce = useCallback(_debounce(findAttach, 300), [data, frame]);
useEffect(() => {
if (didMountRef.current)
findAttachDebounce(form, attachmentIndex);
else
didMountRef.current = true;
}, [form]);
const parseParams = () => {
const attachments = get(frame, 'attachments');
if (!attachments || !attachments.length)
return;
const fields = parseStackParams(attachments);
setFields(fields);
if (attachmentIndex !== undefined) {
if (attachments[attachmentIndex])
setForm(attachments[attachmentIndex].params);
} else
setForm(attachments[0].params);
};
const renderFields = () => {
if (!Object.keys(fields).length)
return null;
const hasSelectField = Object.keys(fields).some(key => fields[key].type === 'select');
return (
<Filters
fields={fields}
form={form}
onChange={onChange}
className={cx(css.filters, {'with-select': hasSelectField})}
/>
);
};
if (loading)
return <Loader />;
if (requestStatus === 403)
return <AccessForbidden>
{t('youDontHaveAnAccessToThisStack')}.
{isSignedIn() && (
<Fragment>
<br />
<Link to={routes.stacks(currentUser)}>
{t('goToMyStacks')}
</Link>
</Fragment>
)}
</AccessForbidden>;
if (requestStatus === 404)
return <NotFound>
{t('theStackYouAreRookingForCouldNotBeFound')}
{' '}
{isSignedIn() && (
<Fragment>
<Link to={routes.stacks(currentUser)}>
{t('goToMyStacks')}
</Link>.
</Fragment>
)}
</NotFound>;
const currentFrame = selectedFrame ? selectedFrame : get(data, 'head.id');
return (
<div className={css.details}>
<Helmet>
<title>dstack.ai | {params.user} | {params.stack}</title>
</Helmet>
<section className={css.section}>
<div className={css.header}>
<div className={css.title}>
{data.name}
<span className={`mdi mdi-lock${data.private ? '' : '-open'}`} />
</div>
{data && data.user === currentUser && (
<Dropdown
className={css.dropdown}
items={[
{
title: t('upload'),
onClick: () => setIsShowUploadModal(true),
},
]}
>
<Button
className={css['dropdown-button']}
color="secondary"
>
<span className="mdi mdi-dots-horizontal" />
</Button>
</Dropdown>
)}
</div>
<Frames
frames={get(data, 'frames', [])}
frame={currentFrame}
headId={headId}
onMarkAsHead={setHeadFrame}
onChange={onChangeFrame}
className={css.revisions}
/>
{!frameRequestStatus && renderFields()}
{attachment && (
<div className={css['attachment-head']}>
{attachment.description && (
<div className={css.description}>
<MarkdownRender source={attachment.description} />
</div>
)}
{attachment.type === 'text/csv' && (
<div className={css.actions}>
<a href="#" onClick={showHowToModal}>{t('useThisStackViaAPI')}</a>
{' '}
{t('or')}
{' '}
<a href="#" onClick={onClickDownloadAttachment}>{t('download')}</a>
{' '}
{attachment.length && (
<span className={css.size}>({formatBytes(attachment.length)})</span>
)}
</div>
)}
</div>
)}
{attachmentRequestStatus === 404 || frameRequestStatus === 404 && (
<div className={css.empty}>{t('noMatch')}</div>
)}
{(frame && !attachmentRequestStatus && !frameRequestStatus) && (
<Attachment
className={css.attachment}
withLoader
stack={`${params.user}/${params.stack}`}
frameId={currentFrame}
id={attachmentIndex || 0}
/>
)}
</section>
<Upload
stack={params.stack}
isShow={isShowUploadModal}
onClose={() => setIsShowUploadModal(false)}
refresh={fetchData}
/>
<Modal
isShow={isShowHowToModal}
withCloseButton
onClose={hideHowToModal}
size="big"
title={t('howToFetchDataUsingTheAPI')}
className={css.modal}
>
<HowToFetchData
data={{
stack: `${params.user}/${params.stack}`,
params: form,
}}
modalMode
/>
</Modal>
</div>
);
}
Example #22
Source File: index.js From dstack-server with Apache License 2.0 | 4 votes |
List = ({
currentUser,
createDashboard,
creatingDashboard,
fetchList,
setSearch,
setSearchPlaceholder,
data,
search,
loading,
requestStatus,
}: Props) => {
const {user} = useParams();
const {push} = useHistory();
const {t} = useTranslation();
const onChangeSearch = value => setSearch(value);
useEffect(() => {
fetchList(user);
}, [user]);
useEffect(() => {
setSearchPlaceholder(t('findDashboard'));
return () => setSearchPlaceholder(null);
}, []);
const getItems = () => {
let items = [];
if (data && data.length) {
if (search.length)
items = data.filter(i => i.title.indexOf(search) >= 0);
else
items = data;
}
return items;
};
const onClickAdd = () => {
createDashboard(
user,
({dashboard}) => push(routes.dashboardsDetails(user, dashboard.id)),
);
};
const items = getItems();
if (loading)
return <Loader />;
if (requestStatus === 404)
return <NotFound>
{t('theDashboardYouAreRookingForCouldNotBeFound')}
{' '}
{isSignedIn() && (
<Fragment>
<Link to={routes.dashboards(currentUser)}>
{t('goToMyDashboards')}
</Link>.
</Fragment>
)}
</NotFound>;
return (
<div className={css.list}>
<div className={css.title}>
{currentUser === user
? t('myDashboards')
: t('dashboardsOf', {name: user})
}
{data && Boolean(data.length) && <span>{data.length}</span>}
</div>
{data && Boolean(data.length) && <SearchField
placeholder={t('search')}
className={css.search}
showEverything
size="small"
value={search}
onChange={onChangeSearch}
/>}
<div className={css.grid}>
{currentUser === user && (
<div
onClick={onClickAdd}
className={cx(css.add, {disabled: creatingDashboard})}
>
<div className={css.caption}>
<span className="mdi mdi-plus" />
{t('newDashboard')}
</div>
</div>
)}
{items.map((item, index) => (
<Item key={index} dashboard={item} />
))}
</div>
</div>
);
}
Example #23
Source File: index.js From dstack-server with Apache License 2.0 | 4 votes |
Details = ({
data,
fetch,
update,
currentUser,
deleteDashboard,
insertCard,
deleteCard,
updateCard,
requestStatus,
loading,
}: Props) => {
const {items, moveItem, setItems} = useContext(DnDGridContext);
const {t} = useTranslation();
const [isShowStacksModal, setIsShowStacksModal] = useState(false);
const [titleValue, setTitleValue] = useState(data ? data.title : '');
const [view, setView] = useState('grid');
const {form, setForm, onChange} = useForm({});
const [fields, setFields] = useState({});
const prevData = usePrevious(data);
const params = useParams();
const {push} = useHistory();
const isDidMount = useRef(true);
const updateDebounce = useCallback(_debounce(update, 300), []);
const cards = data?.cards;
const setGridItems = cardsItems => setItems(cardsItems.map(card => ({id: card.index, card})));
useEffect(() => {
if (!data || data.id !== params.id)
fetch(params.user, params.id);
else
setGridItems(cards);
}, []);
useEffect(() => {
if (window)
window.dispatchEvent(new Event('resize'));
}, [view]);
useEffect(() => {
if (cards && !isEqual(prevData, data))
setGridItems(cards);
return () => setGridItems([]);
}, [cards]);
useEffect(() => {
if (!prevData && data || (prevData && data && prevData.id !== data.id))
setTitleValue(data.title);
if ((!isEqual(prevData, data) || isDidMount.current) && data)
parseParams();
if (isDidMount.current)
isDidMount.current = false;
}, [data]);
const onChangeTitle = event => {
setTitleValue(event.target.value);
updateDebounce({
user: params.user,
id: data.id,
title: event.target.value,
});
};
const moveCard = (indexFrom, indexTo) => {
if (indexTo < 0 || indexFrom < 0)
return;
const {stack} = items[indexFrom].card;
updateCard({
user: params.user,
dashboard: data.id,
stack,
index: indexTo,
});
moveItem(indexFrom, indexTo);
};
const onClickAdd = event => {
event.preventDefault();
setIsShowStacksModal(true);
};
const closeModal = () => setIsShowStacksModal(false);
const onClickDelete = () => {
deleteDashboard(
{
user: params.user,
id: data.id,
},
() => {
push(routes.dashboards(params.user));
}
);
};
const getDeleteCardAction = stack => () => {
deleteCard({
user: params.user,
dashboard: data.id,
stack,
});
};
const getUpdateCardAction = stack => fields => {
updateCard({
user: params.user,
dashboard: data.id,
stack,
...fields,
});
};
const addStacksToDashboard = stacks => {
stacks.forEach((stack, index) => {
insertCard({
user: params.user,
dashboard: params.id,
stack,
index: cards.length + index,
});
});
};
const parseParams = () => {
if (!cards)
return;
const fields = cards.reduce((result, card) => {
const cardFields = parseStackParams(get(card, 'head.attachments', [])) || {};
Object.keys(cardFields).forEach(fieldName => {
if (result[fieldName]) {
if (cardFields[fieldName].type === 'select') {
result[fieldName].options = unionBy(
result[fieldName].options,
cardFields[fieldName].options, 'value');
}
if (cardFields[fieldName].type === 'slider') {
result[fieldName].options = {
...result[fieldName].options,
...cardFields[fieldName].options,
};
result[fieldName].min = Math.min(result[fieldName].min, cardFields[fieldName].min);
result[fieldName].max = Math.max(result[fieldName].max, cardFields[fieldName].max);
}
} else {
result[fieldName] = cardFields[fieldName];
}
});
return result;
}, {});
const defaultFilterValues = Object.keys(fields).reduce((result, fieldName) => {
if (fields[fieldName].type === 'select')
result[fieldName] = fields[fieldName].options[0].value;
if (fields[fieldName].type === 'slider')
result[fieldName] = fields[fieldName].options[0];
if (fields[fieldName].type === 'checkbox')
result[fieldName] = false;
return result;
}, {});
setForm(defaultFilterValues);
setFields(fields);
};
const renderFilters = () => {
if (!Object.keys(fields).length)
return null;
const hasSelectField = Object.keys(fields).some(key => fields[key].type === 'select');
return (
<Filters
fields={fields}
form={form}
onChange={onChange}
className={cx(css.filters, {'with-select': hasSelectField})}
/>
);
};
if (loading)
return <Loader />;
if (requestStatus === 403)
return <AccessForbidden>
{t('youDontHaveAnAccessToThisDashboard')}.
{isSignedIn() && (
<Fragment>
<br />
<Link to={routes.dashboards(currentUser)}>
{t('goToMyDashboards')}
</Link>
</Fragment>
)}
</AccessForbidden>;
if (requestStatus === 404)
return <NotFound>
{t('theDashboardYouAreRookingForCouldNotBeFound')}
{' '}
{isSignedIn() && (
<Fragment>
<Link to={routes.dashboards(currentUser)}>
{t('goToMyDashboards')}
</Link>.
</Fragment>
)}
</NotFound>;
if (!data)
return null;
return (
<div className={css.details}>
<div className={css.header}>
<div className={css.title}>
<StretchTitleField
className={css.edit}
value={titleValue}
onChange={onChangeTitle}
readOnly={currentUser !== data.user}
placeholder={t('newDashboard')}
/>
<span className={`mdi mdi-lock${data.private ? '' : '-open'}`} />
</div>
{/*<Button*/}
{/* className={css.pdf}*/}
{/* color="secondary"*/}
{/*>*/}
{/* <span className="mdi mdi-download" />*/}
{/* PDF*/}
{/*</Button>*/}
{currentUser === data.user && <Dropdown
className={css.dropdown}
items={[
{
title: t('delete'),
onClick: onClickDelete,
},
]}
>
<Button
className={css['dropdown-button']}
color="secondary"
>
<span className="mdi mdi-dots-horizontal" />
</Button>
</Dropdown>}
</div>
{Boolean(items.length) && (
<Fragment>
<div className={css.section}>
<div className={css.fields}>
{renderFilters()}
</div>
<div className={css.controls}>
{currentUser === data.user && (
<a
className={css.addButton}
onClick={onClickAdd}
href="#"
>
<span className="mdi mdi-plus" />
{t('addStack')}
</a>
)}
<ViewSwitcher
value={view}
className={css.viewSwitcher}
onChange={view => setView(view)}
/>
</div>
</div>
<div className={cx(css.cards, view)}>
{items.map(item => (
currentUser === data.user
? <DnDItem
id={item.id}
key={item.card.stack}
onMoveItem={moveCard}
>
<Card
filters={form}
deleteCard={getDeleteCardAction(item.card.stack)}
data={item.card}
type={view}
updateCard={getUpdateCardAction(item.card.stack)}
/>
</DnDItem>
: <Card
key={item.card.stack}
filters={form}
data={item.card}
type={view}
/>
))}
</div>
</Fragment>
)}
{!items.length && (
<div className={css.empty}>
{t('thereAreNoStacksYet')} <br/>
{t('youCanSendStacksYouWantToBeHereLaterOrAddItRightNow')}
{currentUser === data.user && (
<Fragment>
{' '}
<a
className={css.addButton}
onClick={onClickAdd}
href="#"
>{t('addStack')}</a>.
</Fragment>
)}
</div>
)}
{isShowStacksModal && <SelectStacks
isShow={isShowStacksModal}
onClose={closeModal}
onAddStacks={addStacksToDashboard}
/>}
</div>
);
}
Example #24
Source File: index.js From dstack-server with Apache License 2.0 | 4 votes |
SelectStacks = ({
stacks = [],
userData,
loading,
isShow,
fetchList,
onClose,
onAddStacks,
}: Props) => {
const {t} = useTranslation();
const params = useParams();
const [searchQuery, setSearchQuery] = useState('');
const [selected, setSelected] = useState([]);
useEffect(() => {
if (isShow)
fetchList(params.user);
else {
setSelected([]);
setSearchQuery('');
}
}, [isShow]);
const getItems = () => {
let items = [];
if (stacks && stacks.length) {
if (searchQuery.length)
items = stacks.filter(i => i.name.indexOf(searchQuery) >= 0);
else
items = stacks;
}
return items;
};
const items = getItems();
const onChangeSearch = value => setSearchQuery(value);
const getFullStackName = stack => `${stack.user}/${stack.name}`;
const isChecked = stack => {
const stackName = getFullStackName(stack);
return selected.findIndex(i => i === stackName) >= 0;
};
const getOnClickStack = stack => () => {
const stackName = getFullStackName(stack);
if (isChecked(stack)) {
const filtered = selected.filter(i => i !== stackName);
setSelected(filtered);
} else {
setSelected([
...selected,
stackName,
]);
}
};
const submit = () => {
if (onAddStacks)
onAddStacks(selected);
onClose();
};
return (
<Modal
dialogClassName={css.stacks}
isShow={isShow}
title={t('selectStacks')}
onClose={onClose}
withCloseButton
>
{!loading && Boolean(stacks.length) && (
<SearchField
className={css.search}
isDark
size="middle"
showEverything
placeholder={t('findStack')}
value={searchQuery}
onChange={onChangeSearch}
/>
)}
{loading && <Loader />}
{!loading && !stacks.length && (
<div className={css.message}>
{params.user === get(userData, 'user')
? t('youHaveNoStacksYet')
: t('theUserHasNoStacksYetByName', {name: params.user})
}
</div>
)}
{!loading && Boolean(stacks.length && !items.length) && (
<div className={css.text}>
{t('noStacksAreFoundedMatchedTheSearchCriteria')}
</div>
)}
{!loading && Boolean(stacks.length && items.length) && (
<Fragment>
<div className={css.grid}>
{items.map((item, index) => (
<div className={css.item} key={index} onClick={getOnClickStack(item)}>
<CheckboxField
className={css.checkbox}
value={isChecked(item)}
readOnly
/>
<StackItem
data={item}
/>
</div>
))}
</div>
<div className={css.buttons}>
<Button
className={css.button}
color="primary"
variant="contained"
disabled={!selected.length}
onClick={submit}
>
{t('addSelectedStacks')}
</Button>
<Button
className={css.button}
color="secondary"
variant="contained"
onClick={onClose}
>
{t('cancel')}
</Button>
</div>
</Fragment>
)}
</Modal>
);
}
Example #25
Source File: JobsByCompanyName.js From easy-job-intern with MIT License | 4 votes |
JobsByCompanyName = () => {
const { state, dispatch } = useContext(UserContext);
const [jobs, setJobs] = useState([]);
const [loading, setLoading] = useState(true);
const { companyName } = useParams();
// useEffect(() => {
// axios({
// method: "get",
// url: "http://localhost:5000/user/all-jobs",
// headers: {
// Authorization: "Bearer " + localStorage.getItem("jwt"),
// },
// })
// .then((res) => {
// console.log(res);
// if (res.data.error) {
// console.log(res.data.error);
// // alert(res.data.error);
// const notify = () => toast(res.data.error);
// notify();
// } else {
// // if (res && res.data) {
// console.log(res.data.jobs);
// setJobs(res.data.jobs);
// console.log(jobs);
// // }
// }
// })
// .catch((err) => {
// console.log("Error: ", err);
// });
// }, []);
useEffect(() => {
axios({
method: "get",
url: `http://localhost:5000/user/job/companyName/${companyName}`,
headers: {
Authorization: "Bearer " + localStorage.getItem("jwt"),
},
})
.then((res) => {
console.log(res);
setLoading(false);
if (res.data.error) {
console.log(res.data.error);
// alert(res.data.error);
const notify = () => toast(res.data.error);
notify();
} else {
console.log(res.data.Jobs);
setJobs(res.data.Jobs);
console.log(jobs);
}
})
.catch((err) => {
setLoading(false);
console.log("Error: ", err);
});
}, []);
if (jobs && jobs[4]) {
console.log(jobs[4]);
const t = new Date(jobs[4].startDate).toString("YYYY-MM-DD");
console.log(t);
}
const deletePost = (postId) => {
axios({
method: "delete",
url: "http://localhost:5000/employer/delete-job",
data: {
postId,
},
headers: {
Authorization: "Bearer " + localStorage.getItem("jwt"),
"Content-Type": "application/json",
},
})
.then((res) => {
console.log(res);
if (res.data.error) {
console.log(res.data.error);
// alert(res.data.error);
const notify = () => toast(res.data.error);
notify();
} else {
// console.log(res.data.jobs);
// setJobs(res.data.jobs);
// console.log(jobs);
window.location.reload(false);
const notify = () => toast(res.data.message);
notify();
}
})
.catch((err) => {
console.log("Error: ", err);
});
};
return (
<div className="internshipsOuterContainer">
<Toaster />
<Row className="justify-content-xl-start justify-content-lg-around justify-content-sm-center">
{loading ? (
<div className="h-100 w-100 d-flex justify-content-center align-items-center">
<Spinner
animation="border"
variant="light"
style={{
borderColor: "#515b66",
borderRightColor: "transparent",
}}
/>
</div>
) : jobs && !jobs.length > 0 ? (
<Alert
variant="danger"
className="w-100"
style={{
backgroundColor: "#343A40",
border: "none",
color: "#ffc107",
}}
>
No Jobs available right now
</Alert>
) : (
jobs &&
jobs.map((job) => {
return (
<Col
key={job._id}
className="col-xl-4 col-lg-5 col-md-6 col-sm-11 col-12 colPost"
>
<JobsCard
job={job}
deletePost={deletePost}
key={job._id}
userId={state.user._id}
/>
</Col>
);
})
)}
</Row>
</div>
);
}
Example #26
Source File: FreshersJobByCompanyName.js From easy-job-intern with MIT License | 4 votes |
FreshersJobByCompanyName = () => {
const { state, dispatch } = useContext(UserContext);
const [freshersJobs, setFreshersJobs] = useState([]);
const [loading, setLoading] = useState(true);
const { companyName } = useParams();
useEffect(() => {
axios({
method: "get",
url: `http://localhost:5000/user/freshersJob/companyName/${companyName}`,
headers: {
Authorization: "Bearer " + localStorage.getItem("jwt"),
},
})
.then((res) => {
// console.log(res);
setLoading(false);
if (res.data.error) {
// console.log(res.data.error);
// alert(res.data.error);
const notify = () => toast(res.data.error);
notify();
} else {
// console.log(res.data.freshersjobs);
setFreshersJobs(res.data.FreshersJobs);
// console.log(freshersJobs);
}
})
.catch((err) => {
setLoading(false);
console.log("Error: ", err);
});
}, [freshersJobs]);
if (freshersJobs && freshersJobs[4]) {
console.log(freshersJobs[4]);
const t = new Date(freshersJobs[4].startDate).toString("YYYY-MM-DD");
console.log(t);
}
return (
<div className="internshipsOuterContainer">
<Toaster />
<Row className="justify-content-xl-start justify-content-lg-around justify-content-sm-center">
{loading ? (
<div className="h-100 w-100 d-flex justify-content-center align-items-center">
<Spinner
animation="border"
variant="light"
style={{
borderColor: "#515b66",
borderRightColor: "transparent",
}}
/>
</div>
) : freshersJobs && !freshersJobs.length > 0 ? (
<Alert
variant="danger"
className="w-100"
style={{
backgroundColor: "#343A40",
border: "none",
color: "#ffc107",
}}
>
No Fresher Jobs available right now
</Alert>
) : (
freshersJobs &&
freshersJobs.map((fresher) => {
return (
<Col
key={fresher._id}
className="col-xl-4 col-lg-5 col-md-6 col-sm-11 col-12 colPost"
>
<FresherJobCard fresherjob={fresher} userId={state.user._id} />
</Col>
);
})
)}
</Row>
</div>
);
}
Example #27
Source File: Create.jsx From Organizations-Interface with BSD 2-Clause "Simplified" License | 4 votes |
Create = (props) => {
const { address } = useParams();
const { inputRewardToken } = props;
// utils
const [loading, setLoading] = useState(false);
const [currentBlockNumber, setCurrentBlockNumber] = useState(0);
// booleans
const [isDeploy, setIsDeploy] = useState(false);
// reward token
const [selectedRewardToken, setSelectedRewardToken] = useState(inputRewardToken || null);
const [byMint, setByMint] = useState(false);
// setups
const [farmingSetups, setFarmingSetups] = useState([]);
// deploy data
const [treasuryAddress, setTreasuryAddress] = useState(null);
const [hostWalletAddress, setHostWalletAddress] = useState(null);
const [hostDeployedContract, setHostDeployedContract] = useState(null);
const [deployContract, setDeployContract] = useState(null);
const [useDeployedContract, setUseDeployedContract] = useState(false);
const [extensionPayload, setExtensionPayload] = useState("");
const [selectedHost, setSelectedHost] = useState("");
const [deployLoading, setDeployLoading] = useState(false);
const [deployStep, setDeployStep] = useState(0);
const [deployData, setDeployData] = useState(null);
const [farmingExtensionTemplateCode, setFarmingExtensionTemplateCode] = useState("");
const [hasTreasuryAddress, setHasTreasuryAddress] = useState(false);
const [farmingContract, setFarmingContract] = useState("");
const [totalRewardToSend, setTotalRewardToSend] = useState(0);
useEffect(async () => {
//setFarmingExtensionTemplateCode(await (await fetch(FarmingExtensionTemplateLocation)).text());
if (props.farmingContract?.rewardToken) {
onSelectRewardToken(props.farmingContract.rewardToken.address);
} else if (address) {
onSelectRewardToken(address);
}
if (currentBlockNumber === 0) {
props.dfoCore.getBlockNumber().then((blockNumber) => {
setCurrentBlockNumber(blockNumber);
});
}
}, []);
useEffect(() => {
setByMint(false);
}, [selectedRewardToken]);
const addFarmingSetup = (setup) => {
setFarmingSetups(farmingSetups.concat(setup));
}
const editFarmingSetup = (setup, index) => {
const updatedSetups = farmingSetups.map((s, i) => {
return i !== index ? s : setup;
})
setFarmingSetups(updatedSetups);
}
const removeFarmingSetup = (i) => {
const updatedSetups = farmingSetups.filter((_, index) => index !== i);
setFarmingSetups(updatedSetups);
}
const onSelectRewardToken = async (address) => {
setLoading(true);
try {
const rewardToken = await props.dfoCore.getContract(props.dfoCore.getContextElement('ERC20ABI'), address);
const symbol = await rewardToken.methods.symbol().call();
const decimals = await rewardToken.methods.decimals().call();
setSelectedRewardToken({ symbol, address, decimals });
} catch (error) {
console.error(error);
setSelectedRewardToken(null);
} finally {
setLoading(false);
}
}
const initializeDeployData = async () => {
setDeployLoading(true);
try {
const data = { setups: [], rewardTokenAddress: selectedRewardToken.address, byMint, deployContract, extensionInitData: extensionPayload || '' };
const ammAggregator = await props.dfoCore.getContract(props.dfoCore.getContextElement('AMMAggregatorABI'), props.dfoCore.getContextElement('ammAggregatorAddress'));
console.log(farmingSetups);
var calculatedTotalToSend = "0";
for (let i = 0; i < farmingSetups.length; i++) {
const setup = farmingSetups[i];
calculatedTotalToSend =
props.dfoCore.web3.utils.toBN(calculatedTotalToSend).add(
props.dfoCore.web3.utils.toBN(window.numberToString(props.dfoCore.fromDecimals(window.numberToString(setup.rewardPerBlock), selectedRewardToken.decimals)),
).mul(props.dfoCore.web3.utils.toBN(window.numberToString(setup.blockDuration)))
).toString();
const isFree = setup.free;
const result = await ammAggregator.methods.findByLiquidityPool(setup.liquidityPoolToken.address).call();
const { amm } = result;
var mainTokenAddress = isFree ? setup.liquidityPoolToken.tokens[0].address : setup.mainToken.address;
const mainTokenContract = await props.dfoCore.getContract(props.dfoCore.getContextElement('ERC20ABI'), mainTokenAddress);
const mainTokenDecimals = mainTokenAddress === window.voidEthereumAddress ? 18 : await mainTokenContract.methods.decimals().call();
const parsedSetup =
[
isFree,
parseInt(setup.blockDuration),
parseInt(setup.startBlock),
window.numberToString(props.dfoCore.fromDecimals(window.numberToString(setup.rewardPerBlock), selectedRewardToken.decimals)),
window.numberToString(props.dfoCore.fromDecimals(window.numberToString(setup.minStakeable), mainTokenDecimals)),
!isFree ? window.numberToString(props.dfoCore.fromDecimals(window.numberToString(setup.maxStakeable)), mainTokenDecimals) : 0,
setup.renewTimes,
amm,
setup.liquidityPoolToken.address,
mainTokenAddress,
props.dfoCore.voidEthereumAddress,
setup.involvingEth,
isFree ? 0 : props.dfoCore.fromDecimals(window.numberToString(parseFloat(setup.penaltyFee) / 100)),
0,
0
];
data.setups.push(parsedSetup)
}
console.log(data);
setDeployData(data);
setTotalRewardToSend(calculatedTotalToSend);
return data;
} catch (error) {
console.error(error);
setDeployData(null);
} finally {
setDeployLoading(false);
}
}
async function deployDFO() {
var farmingData = await initializeDeployData();
var sequentialOps = [{
name: "Clone Extension",
description: "Farm Extension will comunicate with the DFO for Token and ETH transmission to the Farming Contract Contract",
async call(data) {
var transaction = await window.blockchainCall(dfoBasedFarmExtensionFactory.methods.cloneModel);
var receipt = await window.web3.eth.getTransactionReceipt(transaction.transactionHash);
data.extensionAddress = window.web3.eth.abi.decodeParameter("address", receipt.logs.filter(it => it.topics[0] === window.web3.utils.sha3('ExtensionCloned(address,address)'))[0].topics[1]);
},
onTransaction(data, transaction) {
data.extensionAddress = window.web3.eth.abi.decodeParameter("address", transaction.logs.filter(it => it.topics[0] === window.web3.utils.sha3('ExtensionCloned(address,address)'))[0].topics[1]);
}
}, {
name: "Deploy Farm Contract",
description: 'New Farm Contract will be deployed.',
async call(data) {
var deployPayload = window.newContract(props.dfoCore.getContextElement("FarmMainABI")).methods.init(
data.extensionAddress,
window.web3.utils.sha3("init(bool,address,address)").substring(0, 10) + window.web3.eth.abi.encodeParameters(["bool", "address", "address"], [farmingData.byMint, data.element.doubleProxyAddress, window.voidEthereumAddress]).substring(2),
window.getNetworkElement("ethItemOrchestratorAddress"),
farmingData.rewardTokenAddress,
abi.encode(["tuple(bool,uint256,uint256,uint256,uint256,uint256,uint256,address,address,address,address,bool,uint256,uint256,uint256)[]"], [farmingData.setups])
).encodeABI();
var transaction = await window.blockchainCall(farmFactory.methods.deploy, deployPayload);
var receipt = await window.web3.eth.getTransactionReceipt(transaction.transactionHash);
data.farmAddress = window.web3.eth.abi.decodeParameter("address", receipt.logs.filter(it => it.topics[0] === window.web3.utils.sha3('FarmMainDeployed(address,address,bytes)'))[0].topics[1]);
},
async onTransaction(data, transaction) {
data.farmAddress = window.web3.eth.abi.decodeParameter("address", transaction.logs.filter(it => it.topics[0] === window.web3.utils.sha3('FarmMainDeployed(address,address,bytes)'))[0].topics[1]);
}
}, {
name: "Generate SmartContract Proposal",
async call(data) {
data.selectedSolidityVersion = (await window.SolidityUtilities.getCompilers()).releases['0.7.6'];
data.bypassFunctionalitySourceId = true;
data.contractName = 'ProposalCode';
var fileName = "NewFarmingExtension";
data.functionalityMethodSignature = 'callOneTime(address)';
if (JSON.parse(await window.blockchainCall(data.element.functionalitiesManager.methods.functionalityNames)).filter(it => it === 'manageFarming').length === 0) {
fileName = "ManageFarmingFunctionality";
data.functionalityMethodSignature = 'manageFarming(address,uint256,bool,address,address,uint256,bool)';
data.functionalityName = 'manageFarming';
data.functionalitySubmitable = true;
data.functionalityNeedsSender = true;
}
data.sourceCode = (await (await fetch(`data/${fileName}.sol`)).text()).format(window.web3.utils.toChecksumAddress(data.extensionAddress));
console.log(data.sourceCode);
}
}];
var context = {
element: props.element,
sequentialOps,
sourceCode: 'test',
title: (!props.fixedInflationContractAddress ? 'New' : 'Edit') + ' Farming'
};
window.showProposalLoader(context);
};
const deploy = async () => {
let error = false;
let deployTransaction = null;
setDeployLoading(true);
try {
const { setups, rewardTokenAddress, extensionAddress, extensionInitData } = deployData;
const factoryAddress = props.dfoCore.getContextElement("farmFactoryAddress");
const farmFactory = await props.dfoCore.getContract(props.dfoCore.getContextElement("FarmFactoryABI"), factoryAddress);
const types = [
"address",
"bytes",
"address",
"address",
"bytes",
];
console.log(deployData);
const encodedSetups = abi.encode(["tuple(bool,uint256,uint256,uint256,uint256,uint256,address,address,address,address,bool,uint256,uint256,uint256)[]"], [setups]);
const params = [props.dfoCore.web3.utils.toChecksumAddress(extensionAddress ? extensionAddress : hostDeployedContract), extensionPayload || extensionInitData || "0x", props.dfoCore.getContextElement("ethItemOrchestratorAddress"), rewardTokenAddress, encodedSetups || 0];
console.log(params)
console.log(extensionInitData);
console.log(extensionPayload);
console.log(extensionAddress);
const payload = props.dfoCore.web3.utils.sha3(`init(${types.join(',')})`).substring(0, 10) + (props.dfoCore.web3.eth.abi.encodeParameters(types, params).substring(2));
console.log(payload);
const gas = await farmFactory.methods.deploy(payload).estimateGas({ from: props.dfoCore.address });
deployTransaction = await farmFactory.methods.deploy(payload).send({ from: props.dfoCore.address, gas });
deployTransaction = await props.dfoCore.web3.eth.getTransactionReceipt(deployTransaction.transactionHash);
var farmMainContractAddress = props.dfoCore.web3.eth.abi.decodeParameter("address", deployTransaction.logs.filter(it => it.topics[0] === props.dfoCore.web3.utils.sha3("FarmMainDeployed(address,address,bytes)"))[0].topics[1]);
setFarmingContract(farmMainContractAddress);
} catch (error) {
console.error(error);
error = true;
} finally {
if (!error && deployTransaction) {
props.updateFarmingContract(null);
await Promise.all(farmingSetups.map(async (_, i) => {
removeFarmingSetup(i);
}));
props.setFarmingContractStep(0);
setSelectedRewardToken(null);
setByMint(false);
setDeployStep(deployStep + 1);
}
setDeployLoading(false);
}
}
const deployExtension = async () => {
let error = false;
setDeployLoading(true);
try {
const { byMint, host, deployContract } = deployData;
if (!deployContract) {
const factoryAddress = props.dfoCore.getContextElement("farmFactoryAddress");
const farmFactory = await props.dfoCore.getContract(props.dfoCore.getContextElement("FarmFactoryABI"), factoryAddress);
const cloneGasLimit = await farmFactory.methods.cloneFarmDefaultExtension().estimateGas({ from: props.dfoCore.address });
const cloneExtensionTransaction = await farmFactory.methods.cloneFarmDefaultExtension().send({ from: props.dfoCore.address, gas: cloneGasLimit });
const cloneExtensionReceipt = await props.dfoCore.web3.eth.getTransactionReceipt(cloneExtensionTransaction.transactionHash);
const extensionAddress = props.dfoCore.web3.eth.abi.decodeParameter("address", cloneExtensionReceipt.logs.filter(it => it.topics[0] === props.dfoCore.web3.utils.sha3('ExtensionCloned(address)'))[0].topics[1])
const farmExtension = new props.dfoCore.web3.eth.Contract(props.dfoCore.getContextElement("FarmExtensionABI"), extensionAddress);
const extensionInitData = farmExtension.methods.init(byMint, host, treasuryAddress || props.dfoCore.voidEthereumAddress).encodeABI();
setDeployData({ ...deployData, extensionAddress, extensionInitData });
} else {
const { abi, bytecode } = deployContract;
const gasLimit = await new props.dfoCore.web3.eth.Contract(abi).deploy({ data: bytecode }).estimateGas({ from: props.dfoCore.address });
const extension = await new props.dfoCore.web3.eth.Contract(abi).deploy({ data: bytecode }).send({ from: props.dfoCore.address, gasLimit, gas: gasLimit });
console.log(extension.options.address);
setDeployData({ ...deployData, extensionAddress: extension.options.address });
}
setDeployStep(!error ? deployStep + 1 : deployStep);
} catch (error) {
console.error(error);
error = true;
} finally {
setDeployLoading(false);
}
}
function filterDeployedContract(contractData) {
var abi = contractData.abi;
if (abi.filter(abiEntry => abiEntry.type === 'constructor').length > 0) {
return false;
}
if (abi.filter(abiEntry => abiEntry.type === 'function' && abiEntry.stateMutability !== 'view' && abiEntry.stateMutability !== 'pure' && abiEntry.name === 'transferTo' && (!abiEntry.outputs || abiEntry.outputs.length === 0) && abiEntry.inputs && abiEntry.inputs.length === 1 && abiEntry.inputs[0].type === 'uint256').length === 0) {
return false;
}
if (abi.filter(abiEntry => abiEntry.type === 'function' && abiEntry.stateMutability === 'payable' && abiEntry.name === 'backToYou' && (!abiEntry.outputs || abiEntry.outputs.length === 0) && abiEntry.inputs && abiEntry.inputs.length === 1 && abiEntry.inputs[0].type === 'uint256').length === 0) {
return false;
}
return true;
}
function onHasTreasuryAddress(e) {
setTreasuryAddress("");
setHasTreasuryAddress(e.target.checked);
}
function onTreasuryAddressChange(e) {
var addr = e.currentTarget.value;
setTreasuryAddress(window.isEthereumAddress(addr) ? addr : "");
}
function onHostSelection(e) {
setSelectedHost(e.target.value);
setHostWalletAddress("");
setHostDeployedContract("");
setExtensionPayload("");
setUseDeployedContract(false);
setTreasuryAddress("");
setHasTreasuryAddress(false);
setDeployContract(null);
}
function canDeploy() {
if (!selectedHost) {
return false;
}
if (selectedHost === 'address') {
if (hasTreasuryAddress && !window.isEthereumAddress(treasuryAddress)) {
return false;
}
return window.isEthereumAddress(hostWalletAddress);
}
if (selectedHost === 'deployedContract') {
if (useDeployedContract) {
return window.isEthereumAddress(hostDeployedContract);
}
return deployContract !== undefined && deployContract !== null && deployContract.contract !== undefined && deployContract.contract !== null;
}
return window.isEthereumAddress(hostDeployedContract);
}
const getCreationComponent = () => {
return <div className="CheckboxQuestions">
<h6>Reward token address</h6>
<p className="BreefRecapB">The reward token is the token chosen to reward farmers and can be one per contract.</p>
<TokenInput placeholder={"Reward token"} onClick={onSelectRewardToken} tokenAddress={(selectedRewardToken && selectedRewardToken.address) || ""} text={"Load"} />
{
loading ? <div className="row justify-content-center">
<div className="spinner-border text-secondary" role="status">
<span className="visually-hidden"></span>
</div>
</div> : <>
{selectedRewardToken && <div className="CheckboxQuestions">
<p><Coin address={selectedRewardToken.address} /> {selectedRewardToken.symbol}</p>
<p className="BreefRecapB">If “by reserve” is selected, the input token will be sent from a wallet. If “by mint” is selected, it will be minted and then sent. The logic of this action must be carefully coded into the extension! To learn more, read the Documentation <a>Documentation (coming Soon)</a></p>
<select value={byMint === true ? "true" : "false"} onChange={e => setByMint(e.target.value === 'true')} className="SelectRegular">
<option value="">Select method</option>
{/*!enterInETH &&*/ <option value="true">By mint</option>}
<option value="false">By reserve</option>
</select>
</div>}
{selectedRewardToken && <div className="Web2ActionsBTNs">
<a className="web2ActionBTN" onClick={() => {
props.updateFarmingContract({ rewardToken: { ...selectedRewardToken, byMint } });
setDeployStep(0);
}}>Start</a>
</div>}
</>
}
</div>
}
const getDeployComponent = () => {
if (deployLoading) {
return <div className="col-12">
<div className="row justify-content-center">
<div className="spinner-border text-secondary" role="status">
<span className="visually-hidden"></span>
</div>
</div>
</div>
}
if (deployStep === 1) {
return <div className="col-12 flex flex-column justify-content-center align-items-center">
<div className="row mb-4">
<h6><b>Deploy extension</b></h6>
</div>
<div className="row">
<a onClick={() => setDeployStep(0)} className="backActionBTN mr-4">Back</a>
<a onClick={() => deployExtension()} className="Web3ActionBTN">Deploy extension</a>
</div>
</div>
} else if (deployStep === 2) {
return <div className="col-12 flex flex-column justify-content-center align-items-center">
<div className="row mb-4">
<h6><b>Deploy Farming Contract</b></h6>
</div>
<div className="row">
<a onClick={() => setDeployStep(hostDeployedContract ? 0 : 1)} className="backActionBTN mr-4">Back</a>
<a onClick={() => deploy()} className="Web3ActionBTN">Deploy contract</a>
</div>
</div>
} else if (deployStep === 3) {
return <div className="col-12 flex flex-column justify-content-center align-items-center">
<div className="row mb-4">
<h6 className="text-secondary"><b>Deploy successful!</b></h6>
</div>
</div>
}
return (
<div className="CheckboxQuestions">
<h6>Host</h6>
<p className="BreefRecapB">The host is the Contract, Wallet, DAO, or DFO with permissions to manage and add new setups in this contract. The host permissions are set into the extension contract. If you choose "Standard Extension (Address, wallet)," the extension must have all of the tokens needed to fill every setup rewards. You can also program extension permissions by your Organization, DFO to mint or transfer directly from the treasury, using the DFOhub website or a custom contract (more info in the Documentation).</p>
<select className="SelectRegular" value={selectedHost} onChange={onHostSelection}>
<option value="">Choose the host type</option>
<option value="address">Standard Extension (Address, wallet)</option>
<option value="deployedContract">Custom Extension (Deployed Contract)</option>
<option value="fromSourceCode">Custom Extension (Deploy Contract)</option>
</select>
{
selectedHost === 'address' ? <>
<div className="InputTokensRegular InputRegularB">
<input type="text" className="TextRegular" value={hostWalletAddress || ""} onChange={(e) => setHostWalletAddress(e.target.value.toString())} placeholder={"Wallet address"} aria-label={"Host address"} />
</div>
<div className="CheckboxQuestions">
<h6><input type="checkbox" checked={hasTreasuryAddress} onChange={onHasTreasuryAddress} /> External Treasury</h6>
{hasTreasuryAddress && <input type="text" className="TextRegular" value={treasuryAddress || ""} onChange={onTreasuryAddressChange} placeholder={"Treasury address"} aria-label={"Treasury address"} />}
<p className="BreefRecapB">[Optional] Separate the Extension to the treasury used to send tokens to the Farm contract to activate setups.</p>
</div>
</> : selectedHost === 'fromSourceCode' ? <>
<p className="BreefRecapB">Deploy a custom extension contract. In the IDE, we loaded a simple extension contract, and you can use it as a guide. Before building a custom contract, we kindly recommend reading the Covenants Documentation. Do it at your own risk.</p>
<ContractEditor filterDeployedContract={filterDeployedContract} dfoCore={props.dfoCore} onContract={setDeployContract} templateCode={farmingExtensionTemplateCode} />
<h6>Extension payload</h6>
<div className="InputTokensRegular InputRegularB">
<input type="text" className="TextRegular" value={extensionPayload || ""} onChange={(e) => setExtensionPayload(e.target.value.toString())} placeholder={"Payload"} aria-label={"Payload"} />
</div>
</> : selectedHost === 'deployedContract' ? <>
<div className="InputTokensRegular InputRegularB">
<input type="text" className="TextRegular" value={hostDeployedContract} onChange={(e) => setHostDeployedContract(e.target.value.toString())} placeholder="Insert extension address" aria-label={"Deployed contract address"} />
</div>
<h6>[Optional] Extension payload</h6>
<div className="InputTokensRegular InputRegularB">
<input type="text" className="TextRegular" value={extensionPayload || ""} onChange={(e) => setExtensionPayload(e.target.value.toString())} placeholder={"Payload"} aria-label={"Payload"} />
</div>
</> : <></>
}
<div className="Web2ActionsBTNs">
<a onClick={() => {
setSelectedHost(null);
setIsDeploy(false);
}} className="backActionBTN">Back</a>
<a onClick={() => {
if (!canDeploy()) {
return;
}
initializeDeployData();
setDeployStep(hostDeployedContract ? 2 : 1);
}} className="web2ActionBTN" disabled={!canDeploy()}>Deploy</a>
</div>
</div>
)
}
const getFarmingContractStatus = () => {
return (
<div className="col-12">
<div className="row flex-column align-items-start mb-4">
<h5 className="text-secondary"><b>Farm {props.farmingContract.rewardToken.symbol}</b></h5>
</div>
<CreateOrEditFarmingSetups
rewardToken={selectedRewardToken}
farmingSetups={farmingSetups}
onAddFarmingSetup={addFarmingSetup}
onRemoveFarmingSetup={removeFarmingSetup}
onEditFarmingSetup={editFarmingSetup}
onCancel={() => { props.updateFarmingContract(null); }}
onFinish={deployDFO}
/>
</div>
)
}
if (farmingContract) {
return (
<div>
<h3>Farming Contract Deployed!</h3>
<p>The contract address is <a href={props.dfoCore.getContextElement("etherscanURL") + "address/" + farmingContract} target="_blank">{farmingContract}</a></p>
<p>To activate all the setups you created, {byMint ? "be sure to grant the permission to mint at least" : "you must send"} <b>{window.fromDecimals(totalRewardToSend, selectedRewardToken.decimals, true)}</b> {selectedRewardToken.symbol} <Coin address={selectedRewardToken.address} /> {byMint ? "for the extension" : "to its extension, having address"} <a href={props.dfoCore.getContextElement("etherscanURL") + "address/" + deployData.extensionAddress} target="_blank">{deployData.extensionAddress}</a></p>
<p>If you need more information, copy the two addresses and check documentation.</p>
</div>
);
}
if (isDeploy) {
return (
<div className="create-component">
<div className="row mb-4">
{getDeployComponent()}
</div>
</div>
)
}
return (
<div>
{ !props.farmingContract && getCreationComponent()}
{ props.farmingContract && getFarmingContractStatus()}
</div>
)
}
Example #28
Source File: ExploreFarmingContract.jsx From Organizations-Interface with BSD 2-Clause "Simplified" License | 4 votes |
ExploreFarmingContract = (props) => {
const { dfoCore, farmAddress, withoutBack } = props;
let { address } = useParams();
if (!address) {
address = farmAddress;
}
const isHost = props.edit;
const [farmingSetups, setFarmingSetups] = useState([]);
const [contract, setContract] = useState(null);
const [metadata, setMetadata] = useState(null);
const [isAdd, setIsAdd] = useState(false);
const [loading, setLoading] = useState(true);
const [extension, setExtension] = useState(null);
const [setupsLoading, setSetupsLoading] = useState(false);
const [token, setToken] = useState(null);
const [showOldSetups, setShowOldSetups] = useState(false);
const [newFarmingSetups, setNewFarmingSetups] = useState([]);
const [totalRewardToSend, setTotalRewardToSend] = useState(0);
useEffect(() => {
if (dfoCore) {
getContractMetadata();
}
}, []);
useEffect(() => {
isAdd && !isHost && setIsAdd(false);
});
const getContractMetadata = async () => {
setLoading(true);
try {
const lmContract = await dfoCore.getContract(dfoCore.getContextElement('FarmMainABI'), address);
setContract(lmContract);
const rewardTokenAddress = await lmContract.methods._rewardTokenAddress().call();
const rewardToken = await dfoCore.getContract(dfoCore.getContextElement("ERC20ABI"), rewardTokenAddress);
const rewardTokenSymbol = await rewardToken.methods.symbol().call();
const rewardTokenDecimals = await rewardToken.methods.decimals().call();
setToken({ symbol: rewardTokenSymbol, address: rewardTokenAddress, decimals: rewardTokenDecimals });
const extensionAddress = await lmContract.methods._extension().call();
const extensionContract = await dfoCore.getContract(dfoCore.getContextElement('FarmExtensionABI'), extensionAddress);
setExtension(extensionContract);
const { host, byMint } = await extensionContract.methods.data().call();
const setups = await lmContract.methods.setups().call();
const blockNumber = await dfoCore.getBlockNumber();
const freeSetups = [];
const lockedSetups = [];
let totalFreeSetups = 0;
let totalLockedSetups = 0;
let rewardPerBlock = 0;
let canActivateSetup = false;
const res = [];
for (let i = 0; i < setups.length; i++) {
const { '0': setup, '1': setupInfo } = await props.dfoCore.loadFarmingSetup(lmContract, i);
if (!canActivateSetup) {
canActivateSetup = parseInt(setupInfo.renewTimes) > 0 && !setup.active && parseInt(setupInfo.lastSetupIndex) === parseInt(i);
}
if (setup.rewardPerBlock !== "0") {
setupInfo.free ? totalFreeSetups += 1 : totalLockedSetups += 1;
res.push({ ...setup, setupInfo, rewardTokenAddress, setupIndex: i, finished: (parseInt(blockNumber) > parseInt(setup.endBlock) && parseInt(setup.endBlock) !== 0) || (parseInt(setup.endBlock) === 0 && parseInt(setupInfo.renewTimes) === 0) })
}
if (setup.active && (parseInt(setup.endBlock) > blockNumber)) {
setupInfo.free ? freeSetups.push(setup) : lockedSetups.push(setup);
rewardPerBlock += parseInt(setup.rewardPerBlock);
}
}
const sortedRes = res.sort((a, b) => b.active - a.active);
setFarmingSetups(sortedRes);
const metadata = {
name: `Farm ${rewardTokenSymbol}`,
contractAddress: lmContract.options.address,
rewardTokenAddress: rewardToken.options.address,
rewardPerBlock: dfoCore.toDecimals(dfoCore.toFixed(rewardPerBlock).toString(), rewardTokenDecimals),
byMint,
freeSetups,
lockedSetups,
totalFreeSetups,
totalLockedSetups,
canActivateSetup,
extension: `${extensionAddress.substring(0, 5)}...${extensionAddress.substring(extensionAddress.length - 3, extensionAddress.length)}`,
fullExtension: `${extensionAddress}`,
farmAddress: `${lmContract.options.address.substring(0, 5)}...${lmContract.options.address.substring(lmContract.options.address.length - 3, lmContract.options.address.length)}`,
host: `${host.substring(0, 5)}...${host.substring(host.length - 3, host.length)}`,
fullhost: `${host}`,
};
setMetadata({ contract: lmContract, metadata, isActive: freeSetups + lockedSetups > 0 || canActivateSetup });
} catch (error) {
console.error(error);
} finally {
setLoading(false);
}
}
const isWeth = (address) => {
return (address.toLowerCase() === dfoCore.getContextElement('wethTokenAddress').toLowerCase()) || (address === dfoCore.voidEthereumAddress);
}
const addFarmingSetup = (setup) => {
setNewFarmingSetups(newFarmingSetups.concat(setup));
}
const editFarmingSetup = (setup, index) => {
const updatedSetups = newFarmingSetups.map((s, i) => {
return i !== index ? s : setup;
})
setNewFarmingSetups(updatedSetups);
}
const removeFarmingSetup = (i) => {
const updatedSetups = newFarmingSetups.filter((_, index) => index !== i);
setNewFarmingSetups(updatedSetups);
}
const updateSetups = async () => {
console.log(newFarmingSetups);
setSetupsLoading(true);
try {
const newSetupsInfo = [];
const ammAggregator = await dfoCore.getContract(dfoCore.getContextElement('AMMAggregatorABI'), dfoCore.getContextElement('ammAggregatorAddress'));
var calculatedTotalToSend = "0";
for (var i in newFarmingSetups) {
const setup = newFarmingSetups[i];
calculatedTotalToSend =
props.dfoCore.web3.utils.toBN(calculatedTotalToSend).add(
props.dfoCore.web3.utils.toBN(window.numberToString(props.dfoCore.fromDecimals(window.numberToString(setup.rewardPerBlock), token.decimals)),
).mul(props.dfoCore.web3.utils.toBN(window.numberToString(setup.blockDuration)))
).toString();
const isFree = setup.free;
const result = await ammAggregator.methods.findByLiquidityPool(setup.liquidityPoolToken.address).call();
const { amm } = result;
var mainTokenAddress = isFree ? setup.liquidityPoolToken.tokens[0].address : setup.mainToken.address;
const mainTokenContract = await props.dfoCore.getContract(props.dfoCore.getContextElement('ERC20ABI'), mainTokenAddress);
const mainTokenDecimals = mainTokenAddress === window.voidEthereumAddress ? 18 : await mainTokenContract.methods.decimals().call();
const setupInfo =
{
add: true,
disable: false,
index: 0,
info: {
free: isFree,
blockDuration: parseInt(setup.blockDuration),
startBlock: parseInt(setup.startBlock),
originalRewardPerBlock: window.numberToString(props.dfoCore.fromDecimals(window.numberToString(setup.rewardPerBlock), token.decimals)),
minStakeable: window.numberToString(props.dfoCore.fromDecimals(window.numberToString(setup.minStakeable), mainTokenDecimals)),
maxStakeable : !isFree ? window.numberToString(props.dfoCore.fromDecimals(window.numberToString(setup.maxStakeable)), mainTokenDecimals) : 0,
renewTimes: setup.renewTimes,
ammPlugin: amm,
liquidityPoolTokenAddress: setup.liquidityPoolToken.address,
mainTokenAddress,
ethereumAddress: dfoCore.voidEthereumAddress,
involvingETH: setup.involvingEth,
penaltyFee: isFree ? 0 : props.dfoCore.fromDecimals(window.numberToString(parseFloat(setup.penaltyFee) / 100)),
setupsCount: 0,
lastSetupIndex: 0
}
};
newSetupsInfo.push(setupInfo);
}
await deployDFO(newSetupsInfo);
} catch (error) {
console.error(error);
}
}
async function deployDFO(setups) {
var sequentialOps = [{
name: "Generate SmartContract Proposal",
async call(data) {
data.selectedSolidityVersion = (await window.SolidityUtilities.getCompilers()).releases['0.7.6'];
data.bypassFunctionalitySourceId = true;
data.contractName = 'ProposalCode';
data.functionalityMethodSignature = 'callOneTime(address)';
var fileName = 'FarmingSetFarmingSetupsProposal';
var setupsCode = '';
for(var i in setups) {
var setup = setups[i];
setupsCode += " " +
`farmingSetups[${i}] = FarmingSetupConfiguration(${setup.add}, ${setup.disable}, ${setup.index}, FarmingSetupInfo(${setup.info.free}, ${setup.info.blockDuration}, ${setup.info.startBlock}, ${setup.info.originalRewardPerBlock}, ${setup.info.minStakeable}, ${setup.info.maxStakeable}, ${setup.info.renewTimes}, ${window.web3.utils.toChecksumAddress(setup.info.ammPlugin)}, ${window.web3.utils.toChecksumAddress(setup.info.liquidityPoolTokenAddress)}, ${window.web3.utils.toChecksumAddress(setup.info.mainTokenAddress)}, ${window.web3.utils.toChecksumAddress(setup.info.ethereumAddress)}, ${setup.info.involvingETH}, ${setup.info.penaltyFee}, ${setup.info.setupsCount}, ${setup.info.lastSetupIndex}));` +
"\n";
}
data.sourceCode = (await (await fetch(`data/${fileName}.sol`)).text()).format(setups.length, setupsCode.trim(), metadata.metadata.fullExtension);
console.log(data.sourceCode);
}
}];
var context = {
element: props.element,
sequentialOps,
sourceCode: 'test',
title: 'Manage Farming Setups'
};
window.showProposalLoader(context);
};
if (loading) {
return (<Loading/>);
}
const lockedSetups = farmingSetups.filter((s) => !s.setupInfo.free && !s.finished);
const freeSetups = farmingSetups.filter((s) => s.setupInfo.free && !s.finished);
const finishedSetups = farmingSetups.filter((s) => s.finished);
if(totalRewardToSend) {
return (
<div>
<h3>Congratulations!</h3>
<p>In order to be able to activate the new setups you created, {metadata.metadata.byMint ? "be sure to grant the permission to mint at least" : "you must send"} <b>{window.fromDecimals(totalRewardToSend, token.decimals, true)}</b> {token.symbol} <Coin address={token.address}/> {metadata.metadata.byMint ? "for the extension" : "to its extension, having address"} <a href={props.dfoCore.getContextElement("etherscanURL") + "address/" + metadata.metadata.fullExtension} target="_blank">{metadata.metadata.fullExtension}</a></p>
<a href="javascript:;" onClick={() => setTotalRewardToSend("")}>Got it</a>
</div>
);
}
return (
<div className="ListOfThings">
{
(contract && metadata) ?
<div className="row">
<FarmingComponent className="FarmContractOpen" dfoCore={dfoCore} contract={metadata.contract} metadata={metadata.metadata} goBack={false} withoutBack={withoutBack} hostedBy={isHost} />
</div> : <div />
}
{
isHost && <>
{ !isAdd && <button className="btn btn-primary" onClick={() => setIsAdd(true)}>Add new setups</button>}
</>
}
{isAdd && <div className="ListOfThings">
{false &&
(!isAdd && farmingSetups.length > 0) && <div>
{freeSetups.length > 0 && <h3>Free setups</h3>}
{
freeSetups.map((farmingSetup) => {
return (
<SetupComponent key={farmingSetup.setupIndex} className="FarmSetup" setupIndex={farmingSetup.setupIndex} setupInfo={farmingSetup.setupInfo} lmContract={contract} dfoCore={dfoCore} setup={farmingSetup} hostedBy={isHost} hasBorder />
)
})
}
{lockedSetups.length > 0 && <h3>Locked setups</h3>}
{
lockedSetups.map((farmingSetup) => {
return (
<SetupComponent key={farmingSetup.setupIndex} className="FarmSetup" setupIndex={farmingSetup.setupIndex} setupInfo={farmingSetup.setupInfo} lmContract={contract} dfoCore={dfoCore} setup={farmingSetup} hostedBy={isHost} hasBorder />
)
})
}
{finishedSetups.length > 0 && <a className="web2ActionBTN my-4" onClick={() => setShowOldSetups(!showOldSetups)}>{`${showOldSetups ? 'Hide' : 'Show'} old setups`}</a>}
{(finishedSetups.length > 0 && showOldSetups) && <h3>Old setups</h3>}
{
showOldSetups && finishedSetups.map((farmingSetup) => {
return (
<SetupComponent key={farmingSetup.setupIndex} className="FarmSetup" setupIndex={farmingSetup.setupIndex} setupInfo={farmingSetup.setupInfo} lmContract={contract} dfoCore={dfoCore} setup={farmingSetup} hostedBy={isHost} hasBorder />
)
})
}
</div>
}
{
isAdd && <CreateOrEditFarmingSetups
rewardToken={token}
farmingSetups={newFarmingSetups}
onAddFarmingSetup={(setup) => addFarmingSetup(setup)}
onRemoveFarmingSetup={(i) => removeFarmingSetup(i)}
onEditFarmingSetup={(setup, i) => editFarmingSetup(setup, i)}
onCancel={() => { setNewFarmingSetups([]); setIsAdd(false); }}
onFinish={() => {}}
finishButton={setupsLoading ? <Loading/> : <button className="btn btn-primary" onClick={() => updateSetups()}>Update setups</button>}
forEdit={true}
/>
}
</div>}
</div>
)
}
Example #29
Source File: ImageEdit.js From fireact with MIT License | 4 votes |
ImageEdit = () => {
const mountedRef = useRef(true);
const listName = 'images'
const title = 'Edit Image';
const useStaticData = imagesJson.useStaticData;
const formSchema = imagesJson.formSchema;
const [urlError, setUrlError] = useState(null);
const [titleError, setTitleError] = useState(null);
const validate = () => {
return !urlError && !titleError;
}
const { userData } = useContext(AuthContext);
const { imageId } = useParams();
const [data, setData] = useState(null);
const [isLoading, setIsLoading] = useState(true);
const titleCase = (str) => {
let splitStr = str.toLowerCase().split(' ');
for (let i = 0; i < splitStr.length; i++) {
splitStr[i] = splitStr[i].charAt(0).toUpperCase() + splitStr[i].substring(1);
}
return splitStr.join(' ');
}
const { setBreadcrumb } = useContext(BreadcrumbContext);
useEffect(() => {
setBreadcrumb([
{
to: "/",
text: "Home",
active: false
},
{
to: "/account/"+userData.currentAccount.id+"/",
text: userData.currentAccount.name,
active: false
},
{
to: "/account/"+userData.currentAccount.id+"/"+listName,
text: titleCase(listName),
active: false
},
{
to: null,
text: title,
active: true
}
]);
setIsLoading(true);
if(useStaticData){
GetImageApiStatic(imageId).then(data => {
if (!mountedRef.current) return null
setData(data);
setIsLoading(false);
})
}else{
const Firestore = FirebaseAuth.firestore();
const DocRef = Firestore.doc('/accounts/'+userData.currentAccount.id+'/images/'+imageId);
DocRef.get().then(doc => {
if (!mountedRef.current) return null
setData(doc.data());
setIsLoading(false);
})
}
},[setBreadcrumb, title, listName, userData, imageId, useStaticData]);
useEffect(() => {
return () => {
mountedRef.current = false
}
},[]);
const EditImageApiFirestore = (id, data) => {
const Firestore = FirebaseAuth.firestore();
const DocRef = Firestore.doc('/accounts/'+userData.currentAccount.id+'/images/'+id);
return DocRef.set(data, {merge: true});
}
return (
<>
{isLoading?(
<Paper>
<Box p={2}>
<Loader text="Loading..." />
</Box>
</Paper>
):(
<DataEdit
id = {imageId}
schema = {formSchema}
validation = {validate}
success = {<Alert severity="success">{useStaticData?"Success! No data is saved because the database is a static file. This is just a demo.":"Success! The data is updated."}</Alert>}
handleEdit = {useStaticData?EditImageApiStatic:EditImageApiFirestore}
>
<TextField
label="Image URL"
name="url"
defaultValue={data.url}
fullWidth
onBlur={(e) => {
if(!/^(http|https):\/\/[^ "]+$/.test(e.target.value) || e.target.value.length > 500){
setUrlError("Image URL must be a valid full URL less than 500 characters long.");
}else{
setUrlError(null);
}
}}
error={urlError?true:false}
helperText={urlError}
/>
<TextField
label="Image Title"
name="title"
defaultValue={data.title}
fullWidth
onBlur={(e) => {
if(e.target.value.trim().length < 1 || e.target.value.trim().length > 100){
setTitleError("Image Title must be between 1 to 100 characters.");
}else{
setTitleError(null);
}
}}
error={titleError?true:false}
helperText={titleError}
/>
</DataEdit>
)}
</>
)
}