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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
/* 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 vote down vote up
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 vote down vote up
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 />
          &nbsp;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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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>
        )}
        </>
    )

}