@material-ui/core#Chip JavaScript Examples

The following examples show how to use @material-ui/core#Chip. 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: BetaBanner.js    From akashlytics-deploy with GNU General Public License v3.0 6 votes vote down vote up
BetaBanner = () => {
  const [isBetaBarVisible, setIsBetaBarVisible] = useState(true);
  const classes = useStyles();

  const onCloseClick = () => {
    localStorage.setItem("isBetaBannerSeen", true);

    setIsBetaBarVisible(false);
  };

  return (
    <>
      {isBetaBarVisible && (
        <Dialog open={true} maxWidth="xs" fullWidth>
          <DialogContent className={classes.dialogContent}>
            <Typography variant="h3">
              <strong>Welcome!</strong>
            </Typography>
            <Box padding="1rem 0">
              <Chip label="BETA" color="secondary" className={classes.betaChip} size="small" />
            </Box>
            <div className={classes.betaText}>
              <Typography variant="body1">
                <strong>Akashlytics Deploy</strong> is currently in <strong>BETA</strong>. We strongly suggest you start with a new wallet and a small amount of
                AKT until we further stabilize the product. Enjoy!
              </Typography>
            </div>
          </DialogContent>
          <DialogActions>
            <Button variant="contained" onClick={onCloseClick} type="button" color="primary">
              Got it!
            </Button>
          </DialogActions>
        </Dialog>
      )}
    </>
  );
}
Example #2
Source File: DataPreview.js    From Otto with MIT License 6 votes vote down vote up
export default function DataPreview() {
  const { state } = useState();
  const classes = useStyles();

  if (state.sample_dataset == null) {
    return null;
  }
  const metadata = datasetMetadata[state.sample_dataset];
  function getFormatted(label, index) {
    if (metadata.units) {
      return label + " (" + metadata.units[index] + ")";
    }
    return label;
  }

  return (
    <Grid direction="column" container className={classes.noPadding}>
      {/* Data Attributes */}
      <Grid item>
        <div className={classes.root}>
          {chipData(state).map((data, index) => {
            return (
              <li key={index}>
                <Chip label={data} color="primary" className={classes.chip} />
              </li>
            );
          })}
        </div>
      </Grid>
      {/* Table */}
      <Grid item className={classes.fullWidth}>
        <TableContainer component={Paper} className={classes.table}>
          <Table size="small" aria-label="a dense table">
            <TableHead>
              <TableRow>
                {metadata.columns.map((column, index) => (
                  <TableCell key={index}>
                    {getFormatted(
                      metadata.columnsMap
                        ? metadata.columnsMap[column]
                        : column,
                      index
                    )}
                  </TableCell>
                ))}
              </TableRow>
            </TableHead>
            <TableBody>
              {metadata.data.slice(0, 5).map((row, index) => (
                <TableRow key={index}>
                  {metadata.columns.map((column, index) => (
                    <TableCell key={index} component="th" scope="row">
                      {row[column]}
                    </TableCell>
                  ))}
                </TableRow>
              ))}
            </TableBody>
          </Table>
        </TableContainer>
      </Grid>
    </Grid>
  );
}
Example #3
Source File: card.js    From dscbppimt-official-website with MIT License 6 votes vote down vote up
AboutCard = ({ image, title, body, hashtag }) => {
    const classes = useStyles()
    return(
        <Card elevation={2} className={classes.aboutCard}>
            <CardContent className={classes.aboutCardContent}>
                {image}
                <Typography variant="subtitle1" component="h5" className={classes.aboutCardTitle}>{title}</Typography>
                <Typography variant="body2" component="p" className={classes.aboutCardBody}>{body}</Typography>
                <Chip label={hashtag}/>
            </CardContent>
        </Card>
        )
}
Example #4
Source File: TagsManager.js    From Edlib with GNU General Public License v3.0 6 votes vote down vote up
renderTags() {
        return this.props.tags.map((tag) => {
            return (
                <Chip
                    onDelete={() => this.handleRemove(tag)}
                    key={'tag-' + tag}
                    className={this.props.classes.chip}
                    label={tag}
                />
            );
        });
    }
Example #5
Source File: Table.js    From react-code-splitting-2021-04-26 with MIT License 6 votes vote down vote up
export default function TableComponent({ data }) {
  const classes = useStyles();
  var keys = Object.keys(data[0]).map(i => i.toUpperCase());
  keys.shift(); // delete "id" key

  return (
    <Table className="mb-0">
      <TableHead>
        <TableRow>
          {keys.map(key => (
            <TableCell key={key}>{key}</TableCell>
          ))}
        </TableRow>
      </TableHead>
      <TableBody>
        {data.map(({ id, name, email, product, price, date, city, status }) => (
          <TableRow key={id}>
            <TableCell className="pl-3 fw-normal">{name}</TableCell>
            <TableCell>{email}</TableCell>
            <TableCell>{product}</TableCell>
            <TableCell>{price}</TableCell>
            <TableCell>{date}</TableCell>
            <TableCell>{city}</TableCell>
            <TableCell>
              <Chip label={status} classes={{root: classes[states[status.toLowerCase()]]}}/>
            </TableCell>
          </TableRow>
        ))}
      </TableBody>
    </Table>
  );
}
Example #6
Source File: index.js    From yi-note with GNU General Public License v3.0 6 votes vote down vote up
Tags = () => {
  const { tags } = useStoreState(state => state.page.data);

  const handleTagClick = tag => {
    browser.runtime.sendMessage({
      action: 'open-options',
      data: { action: 'filter-by-tags', data: [tag] }
    });
  };

  return (
    <Grid container spacing={1}>
      {tags.map(tag => (
        <Grid item key={tag}>
          <Chip
            label={tag}
            color="default"
            clickable
            onClick={handleTagClick.bind(null, tag)}
          />
        </Grid>
      ))}
    </Grid>
  );
}
Example #7
Source File: Footer.js    From akashlytics-deploy with GNU General Public License v3.0 5 votes vote down vote up
Footer = () => {
  const classes = useStyles();
  const { appVersion } = useAppVersion();

  return (
    <AppBar position="fixed" color="default" elevation={0} component="footer" className={classes.root} id="footer">
      <Toolbar variant="dense" className={classes.toolbar}>
        <Box display="flex" alignItems="center">
          {appVersion && (
            <>
              <Typography variant="caption" className={classes.caption}>
                <strong>v{appVersion}</strong>
              </Typography>

              <Chip label="beta" color="secondary" size="small" className={classes.betaChip} />
            </>
          )}

          <LinkTo onClick={() => window.electron.openUrl("https://akash.network")} className={classes.akashLink}>
            <img src="./images/powered-by-akash.svg" alt="Akashlytics Logo" className={classes.akashImage} />
          </LinkTo>
        </Box>

        <Box display="flex" alignItems="center">
          <Box marginRight="1rem">
            <Button
              onClick={() => window.electron.openUrl("https://www.mintscan.io/akash/validators/akashvaloper14mt78hz73d9tdwpdvkd59ne9509kxw8yj7qy8f")}
              size="small"
            >
              <Typography variant="caption" className={classes.caption}>
                Validator
              </Typography>
            </Button>
          </Box>

          <ul className={classes.socialLinks}>
            <li>
              <LinkTo onClick={() => window.electron.openUrl("https://discord.gg/rXDFNYnFwv")} className={classes.socialLink}>
                <DiscordIcon className={classes.socialIcon} />
              </LinkTo>
            </li>
            <li>
              <LinkTo
                onClick={() => window.electron.openUrl("https://www.youtube.com/channel/UC1rgl1y8mtcQoa9R_RWO0UA?sub_confirmation=1")}
                className={classes.socialLink}
              >
                <YouTubeIcon className={classes.socialIcon} />
              </LinkTo>
            </li>
            <li>
              <LinkTo onClick={() => window.electron.openUrl("https://twitter.com/akashlytics")} className={classes.socialLink}>
                <TwitterIcon className={classes.socialIcon} />
              </LinkTo>
            </li>
            <li>
              <LinkTo onClick={() => window.electron.openUrl("https://github.com/Akashlytics/akashlytics-deploy")} className={classes.socialLink}>
                <GitHubIcon className={classes.socialIcon} />
              </LinkTo>
            </li>
          </ul>
        </Box>
      </Toolbar>
    </AppBar>
  );
}
Example #8
Source File: QuesCard.js    From stack-underflow with MIT License 5 votes vote down vote up
QuesCard = ({ question }) => {
  const classes = useQuesCardStyles();

  const {
    id,
    title,
    author,
    body,
    tags,
    points,
    views,
    answerCount,
    createdAt,
  } = question;

  return (
    <Paper elevation={0} className={classes.root}>
      <div className={classes.infoWrapper}>
        <div className={classes.innerInfo}>
          <Typography variant="body2" className={classes.mainText}>
            {points}
          </Typography>
          <Typography variant="caption">votes</Typography>
        </div>
        <div className={classes.innerInfo}>
          <Typography variant="body2" className={classes.mainText}>
            {answerCount}
          </Typography>
          <Typography variant="caption">answers</Typography>
        </div>
        <Typography variant="caption" noWrap>
          {views} views
        </Typography>
      </div>
      <div className={classes.quesDetails}>
        <Typography
          variant="body2"
          color="secondary"
          className={classes.title}
          component={RouterLink}
          to={`/questions/${id}`}
        >
          {title}
        </Typography>
        <Typography variant="body2" style={{ wordWrap: 'anywhere' }}>
          {body.length > 150 ? body.slice(0, 150) + '...' : body}
        </Typography>
        <div className={classes.bottomWrapper}>
          <div className={classes.tagsWrapper}>
            {tags.map((t) => (
              <Chip
                key={t}
                label={t}
                variant="outlined"
                color="primary"
                size="small"
                component={RouterLink}
                to={`/tags/${t}`}
                className={classes.tag}
                clickable
              />
            ))}
          </div>
          <PostedByUser
            username={author.username}
            userId={author.id}
            createdAt={createdAt}
          />
        </div>
      </div>
    </Paper>
  );
}
Example #9
Source File: ProductOptions.js    From beluga with GNU General Public License v3.0 5 votes vote down vote up
function ProductOptions(props) {
  const { variant, handleNameChange, onSave, inEditMode } = props;

  const [variantOptionText, setVariantOptionText] = useState("");

  return (
    <div>
      <div style={{ display: "flex", alignItems: "center" }}>
        {(onSave && !inEditMode) ? (
          <div style={{ fontWeight: "bold", margin: "0 40px 10px 0" }}>
            {variant.name}
          </div>
        ) : (
          <TextField
            label="Option Name (i.e. Size, Color)"
            style={{ width: "350px" }}
            value={variant.name}
            onChange={(e) => handleNameChange(e.target.value)}
            margin="normal"
          />
        )}
        { onSave && inEditMode && (
          <Button
            onClick={onSave}
            variant="outlined" color="secondary" size="small"
            style={{ verticalAlign: "bottom", margin: "0 40px" }}
          >
            Save
          </Button>
        )}
        <div style={{ margin: "0 0 10px 40px", verticalAlign: "bottom", display: "inline-block" }}>
          { variant.options.map((v,i) => (
            <Chip key={`variant${i}`}
              label={v.label}
              onDelete={() => props.deleteVariantOption(i)}
              color="secondary"
              variant="outlined"
              style={{ marginRight: "10px" }}
            />
          ))}
        </div>
      </div>
      <Step disabled={onSave && inEditMode}>
        <TextField
          label="Option Value (i.e. Medium, Blue)"
          value={variantOptionText}
          onChange={(e) => setVariantOptionText(e.target.value)}
          margin="normal"
          size="small"
          style={{ width: "350px" }}
        />
        <Button
          onClick={() => {
            props.addVariantOption(variantOptionText);
            setVariantOptionText("");
          }}
          variant="outlined" color="secondary" size="small"
          style={{ verticalAlign: "bottom", margin: "0 0 10px 40px" }}
        >
          Add
        </Button>
      </Step>
    </div>
  );
}
Example #10
Source File: Header.js    From spells-fyi with MIT License 5 votes vote down vote up
Header = () => {
    const classes = useStyles();
    return (
      <Grid className={classes.topBar}
          container 
          direction="row" 
          alignItems="center" 
          justify="space-between"
      >
      <Grid item>
        <Grid
          container
          direction="row"
          justify="flex-start"
          alignItems="center"
          wrap="nowrap"
        >
          <img src={ Blocky } className={classes.logo} alt="Blocklytics" />
          <Typography className={classes.logoText}>Spells</Typography>
          <Chip label=".fyi" className={classes.fyiTag} />
        </Grid>
      </Grid>
      <Grid item>
        <Grid container direction="row" alignItems="center" justify="flex-end" spacing={2}>
          <Grid item>
            <Button color="primary" href="https://github.com/blocklytics/spells-fyi" target="_blank">Code</Button>
          </Grid>
          <Grid item>
            <Button color="primary" href="https://thegraph.com/explorer/subgraph/blocklytics/spells" target="_blank">Data</Button>
          </Grid>
          {/* <Grid item>
            <Button color="primary">Bounties</Link>
          </Grid> */}
          <Grid item>
            <Button color="primary" href="https://twitter.com/spellsfyi" target="_blank">Twitter</Button>
          </Grid>
          <Grid item>
            <Button color="primary" href="https://discordapp.com/invite/GFxFN3K" target="_blank">Discord</Button>
          </Grid>
          <Grid item>
            <Button color="primary" href="https://gitcoin.co/grants/601/spellsfyi-see-the-future" target="_blank">GitCoin</Button>
          </Grid>
        </Grid>
      </Grid>
      </Grid>
    )
}
Example #11
Source File: MentorCard.js    From mentors-website with MIT License 5 votes vote down vote up
MentorCard = (props) => {
  const classes = useStyles();
  const {
    mentor,
    choseCountry,
    choseSkill,
    heartedMentor,
    toggleHeartedMentor,
  } = props;

  const handleFlagClick = () => {
    choseCountry(mentor.countryAlpha2Code)
  }

  const handleSkillChipClick = (e) => {
    choseSkill(e.target.textContent)
  }
  return (
    <Card className={classes.root}>
      <CardHeader
        avatar={
          <Avatar
            src={`https://unavatar.now.sh/twitter/${mentor.twitter}`}
            aria-label="mentor"
            className={classes.avatar}
          >
            {mentor.name[0]}
          </Avatar>
        }
        action={
          <IconButton onClick={handleFlagClick}>
            <img
              src={`https://www.countryflags.io/${mentor.countryAlpha2Code}/flat/32.png`}
              alt={mentor.country}
            />
          </IconButton>
        }
        title={mentor.name}
        subheader={mentor.title}
      />
      <CardContent className={classes.MessageCardContent}>
        <Typography variant="body2">"{mentor.message}"</Typography>
      </CardContent>
      <CardContent className={classes.SkillsCardContent}>
        <Grid container justify="center" spacing={1}>
          {mentor.skills.map((skill, index) => (
            <Grid key={index} item>
              <Chip label={skill} variant="outlined" onClick={handleSkillChipClick} />
            </Grid>
          ))}
        </Grid>
      </CardContent>
      <Divider variant="fullWidth" />
      <CardActions className={classes.cardAction} disableSpacing>
        <Button href="#connect-mentor" color="primary">
          Connect
        </Button>
        <IconButton onClick={() => toggleHeartedMentor(mentor.id)}>
          {heartedMentor ? (
            <FavoriteOutlinedIcon color="secondary" />
          ) : (
            <FavoriteBorderOutlinedIcon />
          )}
        </IconButton>
      </CardActions>
    </Card>
  );
}
Example #12
Source File: Highlightable.js    From dataqa with GNU General Public License v3.0 5 votes vote down vote up
getRanges() {
    const newText = [];
    let lastRange;

    // For all the characters on the text
    for(let textCharIndex = 0;textCharIndex < this.props.text.length;textCharIndex++) {
      const range = this.getRange((this.props.startChar || 0) + textCharIndex);
      if(range){
        console.log("char index ", textCharIndex, "startChar ", this.props.startChar , range);
      }
      const url = getUrl(textCharIndex, this.props.text);
      const isEmoji = emojiRegex().test(this.props.text[textCharIndex] + this.props.text[textCharIndex + 1]);
      // Get the current character node
      const node = this.getNode(textCharIndex, range, this.props.text, url, isEmoji);

      // If the next node is an url one, we fast forward to the end of it
      if(url.length) {
        textCharIndex += url.length - 1;
      } else if(isEmoji) {
        // Because an emoji is composed of 2 chars
        textCharIndex++;
      }

      if(!range) {
        newText.push(node);
        continue;
      }

      // If the char is in range
      lastRange = range;
      // We put the first range node on the array
      const letterGroup = [node];

      // For all the characters in the highlighted range
      let rangeCharIndex = textCharIndex + 1;

      for(;rangeCharIndex < parseInt(range.end - (this.props.startChar || 0)) + 1;rangeCharIndex++) {
        const isEmoji = emojiRegex().test(`${this.props.text[rangeCharIndex]}${this.props.text[rangeCharIndex + 1]}`);

        if(isEmoji) {
          letterGroup.push(this.getEmojiNode(rangeCharIndex, range));
          // Because an emoji is composed of 2 chars
          rangeCharIndex++;
        } else {
          letterGroup.push(this.getLetterNode(rangeCharIndex, range));
        }

        textCharIndex = rangeCharIndex;
      }
      // const RangeText = letterGroup.map((node) => node.props.children).join('');

      // if range does not have entityId (ED), then assign default color
      let color, variant;
      if((typeof range.entityId) === "undefined"){
        color = colors["grey"][100];
        variant='outlined';
      }else{
        color = colors[this.props.entityColourMap[range.entityId]][200];
      }

      newText.push(<Chip 
                      key={`chip-${textCharIndex}`} 
                      style={{backgroundColor: color}}
                      label={letterGroup} 
                      onDelete={this.props.onDeleteRange? () => this.props.onDeleteRange(range) : undefined}
                      variant={variant}
                    />);
    }

    return newText;
  }
Example #13
Source File: Facets.js    From azure-search-react-template with MIT License 5 votes vote down vote up
export default function Facets(props) {

    function mapFacetName(facetName) {
        const capitalizeFirstLetter = (string) =>
            string[0] ? `${string[0].toUpperCase()}${string.substring(1)}` : '';
        facetName = facetName.trim();
        facetName = capitalizeFirstLetter(facetName);

        facetName = facetName.replace('_', ' ');
        return facetName;
    }

    function addFilter(name, value) {
        const newFilters = props.filters.concat({ field: name, value: value });
        props.setFilters(newFilters);
    }

    function removeFilter(filter) {      
        const newFilters = props.filters.filter((item) => item.value !== filter.value);
        props.setFilters(newFilters);
    }

    var facets;
    try{
        facets = Object.keys(props.facets).map(key => {
            return <CheckboxFacet 
                key={key}
                name={key} 
                values={props.facets[key]}
                addFilter={addFilter}
                removeFilter={removeFilter}
                mapFacetName={mapFacetName}
                selectedFacets={props.filters.filter( f => f.field === key)}
              />;
          });
    } catch (error) {
        console.log(error);
    }

    const filters = props.filters.map((filter, index) => {
            return (
            <li key={index}>
                <Chip 
                    label={`${mapFacetName(filter.field)}: ${filter.value}`} 
                    onDelete={() => removeFilter(filter)}
                    className="chip"
              />
            </li>);
          });


    return (
        <div id="facetPanel" className="box">
            <div className="facetbox">
                <div id="clearFilters">
                <ul className="filterlist">
                    {filters}
                </ul>
                </div>
                <FacetList component="nav" className="listitem" >
                    {facets}
                </FacetList>    
            </div>
        </div>
    );
}
Example #14
Source File: BmcDialog.js    From budgie-stream with MIT License 5 votes vote down vote up
export default function BmcDialog(props) {
  const { close } = props;
  const classes = useStyles();
  const [supporters, setSupporters] = useState({});

  const loadSupporters = async () => {
    const response = await fetch(
      "https://filahf.github.io/budgie-stream-supporters/supporters.json"
    );
    const data = await response.json();
    setSupporters(data.supporters);
  };

  useEffect(() => {
    loadSupporters();
  }, []);

  return (
    <div>
      <Dialog
        onClose={close}
        aria-labelledby="customized-dialog-title"
        open={props.open}
        scroll="paper"
        maxWidth="xs"
      >
        <DialogTitle
          id="customized-dialog-title"
          style={{ textAlign: "center", marginBottom: 0, paddingBottom: 0 }}
        >
          Sponsors & Supporters
        </DialogTitle>
        <DialogContent>
          <Typography>
            This project is open source and free to use. If you would like to
            support the development of Budgie Stream, consider buying me a
            coffee.
          </Typography>
          <div className={classes.action}>
            <Typography style={{ marginTop: "1.5rem" }} variant="subtitle2">
              Supporters
            </Typography>
          </div>
          <div className={classes.root}>
            {Object.entries(supporters).length === 0 ? (
              <Chip variant="outlined" label="No supporters yet" />
            ) : (
              supporters.sort(compare).map((supporter, id) => (
                <Tooltip
                  key={id}
                  title={"Bought " + supporter.value + " coffee(s)!"}
                  placement="top"
                  arrow
                >
                  <Chip
                    icon={<FavoriteIcon style={{ color: "#bf616a" }} />}
                    variant="outlined"
                    label={supporter.name}
                  />
                </Tooltip>
              ))
            )}
          </div>
        </DialogContent>
        <MuiDialogActions className={classes.action}>
          <Button
            variant="contained"
            color="secondary"
            style={{ textTransform: "none" }}
            onClick={handleClick}
          >
            Buy me a coffee
          </Button>
        </MuiDialogActions>
      </Dialog>
    </div>
  );
}
Example #15
Source File: positions.jsx    From GraphVega with MIT License 5 votes vote down vote up
Positions = props => {
  return (
    <Row>
      <Col sm={{span:12}}>
        <Card>
          <CardContent>
          <Typography variant="h6" display="block" gutterBottom>
            Positions
          </Typography>
            <Table>
              <TableHead>
                <TableRow>
                  <TableCell>TYPE</TableCell>
                  <TableCell>QTY</TableCell>
                  <TableCell>MARK</TableCell>
                  <TableCell>STRIKE</TableCell>
                  <TableCell>EXPIRY</TableCell>
                  <TableCell>IMP VOL</TableCell>
                  <TableCell>VEGA</TableCell>
                  <TableCell>THETA</TableCell>
                  <TableCell>DELTA</TableCell>
                  <TableCell>GAMMA</TableCell>
                </TableRow>
              </TableHead>
              <TableBody>
                {props.positions.map((option) => (
                  <TableRow>
                    <TableCell>
                      <Chip label={option.option_type} color={chipStyle(option.option_type)}/>
                    </TableCell>
                    <TableCell>{option.quantity}</TableCell>
                    <TableCell>{(option.bid + option.ask)/2}</TableCell>
                    <TableCell>{option.strike}</TableCell>
                    <TableCell>{expiry(option.expiration_date)}</TableCell>
                    <TableCell>{roundOne(option.greeks.smv_vol*100)}%</TableCell>
                    <TableCell>{option.greeks.vega}</TableCell>
                    <TableCell>{option.greeks.theta}</TableCell>
                    <TableCell>{option.greeks.delta}</TableCell>
                    <TableCell>{option.greeks.gamma}</TableCell>
                  </TableRow>
                ))}
                {(props.quantity && props.quantity !== 0) ? 
                  <TableRow>
                    <TableCell>
                      <Chip label={"shares"} />
                    </TableCell>
                    <TableCell>{props.quantity}</TableCell>
                    <TableCell>{(props.quote.ask + props.quote.bid)/2}</TableCell>
                    <TableCell>--</TableCell>
                    <TableCell>--</TableCell>
                    <TableCell>--</TableCell>
                    <TableCell>--</TableCell>
                    <TableCell>--</TableCell>
                    <TableCell>{props.quantity}</TableCell>
                    <TableCell>--</TableCell>
                  </TableRow>
                : ""
                }
              </TableBody>
            </Table>
          </CardContent>
        </Card>
      </Col>
    </Row>
  )
}
Example #16
Source File: index.js    From yi-note with GNU General Public License v3.0 5 votes vote down vote up
TagDialog = ({ tags, onAddTag, onRemoveTag }) => {
  const { t } = useTranslation('tagdialog');
  const {
    tagDialog: { open }
  } = useStoreState(state => state);
  const {
    tagDialog: { setOpen }
  } = useStoreActions(actions => actions);
  const [input, setInput] = useState('');
  const containerRef = useRef(null);

  useEffect(() => {
    containerRef.current = document.getElementById(APP_ID);
  }, []);

  const handleClose = () => {
    setOpen(false);
  };

  const handleInputChange = e => {
    setInput(e.target.value);
  };

  const handleKeyPress = e => {
    if (e.key === 'Enter') {
      onAddTag(input);
      setInput('');
    }
  };

  const handleDelete = tag => {
    onRemoveTag(tag);
  };

  return (
    <Dialog onClose={handleClose} open={open} container={containerRef.current}>
      <DialogContent>
        <Grid container direction="column" spacing={3}>
          <Grid item>
            <TextField
              autoFocus
              label={t('input.label')}
              value={input}
              onChange={handleInputChange}
              onKeyPress={handleKeyPress}
            />
          </Grid>
          <Grid item container spacing={1}>
            {tags.map(tag => (
              <Grid item key={tag}>
                <Chip
                  label={tag}
                  color="default"
                  onDelete={handleDelete.bind(null, tag)}
                />
              </Grid>
            ))}
          </Grid>
        </Grid>
      </DialogContent>
    </Dialog>
  );
}
Example #17
Source File: Disruption.js    From warsinhk with MIT License 5 votes vote down vote up
Disruption = props => {
  const { node, onCategoryClick } = props
  const { i18n, t } = useTranslation()
  const [expanded, setExpanded] = React.useState(false)

  const handleExpandClick = () => {
    setExpanded(!expanded)
  }

  const sourceUrl = withLanguage(i18n, node, "source_url")
  const hasDescription = props.children && props.children.length > 0
  const ExpandIcon = expanded ? InvertedExpandMoreIcon : ExpandMoreIcon

  return (
    <DisruptionCard>
      <DisruptionCardHeader title={withLanguage(i18n, node, "name")} />
      <DisruptionCardContent>
        <Box alignItems="flex-start">
          <Row>
            <Chip
              label={withLanguage(i18n, node, "category")}
              size="small"
              variant="outlined"
              onClick={() =>
                onCategoryClick(withLanguage(i18n, node, "category"))
              }
            />
          </Row>
          <Row>
            <DisruptionDetail variant="body1">
              {withLanguage(i18n, node, "detail")}
            </DisruptionDetail>
          </Row>
          <Row>
            {t("disruption.status")}:{" "}
            {withLanguage(i18n, node, "status") || "-"}
          </Row>
          <Row>
            {t("disruption.to")}: {withLanguage(i18n, node, "to") || "-"}
          </Row>
        </Box>
      </DisruptionCardContent>
      <>
        <DisruptionCardActions disableSpacing>
          <DisruptionAction>
            {sourceUrl && (
              <Row>
                <Typography variant="caption">
                  <Link component={Link} href={sourceUrl} target="_blank">
                    {t("disruption.source")}
                  </Link>
                </Typography>
              </Row>
            )}
            <Row>
              <Typography variant="caption">
                {t("disruption.last_updated", { date: node.last_update })}
              </Typography>
            </Row>
          </DisruptionAction>
          {hasDescription && (
            <IconButton onClick={handleExpandClick} aria-expanded={expanded}>
              <ExpandIcon />
            </IconButton>
          )}
        </DisruptionCardActions>
        {hasDescription && (
          <Collapse in={expanded} timeout="auto" unmountOnExit>
            <DisruptionCardContent>
              {hasDescription && (
                <Box alignItems="flex-start">{props.children}</Box>
              )}
            </DisruptionCardContent>
          </Collapse>
        )}
      </>
    </DisruptionCard>
  )
}
Example #18
Source File: PageRegion.js    From covid-19 with MIT License 5 votes vote down vote up
Graphs = (props) => {
  const classes = useGraphStyles();
  const world = useContext(WorldContext);
  const name = world.get(props.path, NameComponent);
  const basic = world.get(props.path, BasicDataComponent);
  const population = world.get(props.path, PopulationComponent);

  const [comparingWith, setComparingWith] = React.useState(() => []);
  const addComparison = (path) => {
    const name = world.get(path, NameComponent);
    const basic = world.get(path, BasicDataComponent);
    const population = world.get(path, PopulationComponent);
    setComparingWith(comparingWith.concat([{
      path,
      name,
      basic,
      population
    }]));
  };
  const removeComparison = (i) => {
    const copied = [...comparingWith];
    copied.splice(i, 1);
    setComparingWith(copied);
  };

  return (
    <div className={props.className}>
      <div className={classes.comparisons}>
        <Typography>Compare with: </Typography>
        <SearchInput
          className={classes.comparisonSearch}
          onChoice={addComparison}
        />
        {comparingWith.map(({ path, name }, i) => {
          return (
            <Chip
              key={path.string()}
              className={classes.chip}
              onDelete={() => removeComparison(i)}
              label={name.english()}
            />
          );
        })}
      </div>

      {[DailyChangeGraph, DailyTotalGraph, DoublingGraph].map((Graph, i) => (
        <Graph
          key={i}
          name={name}
          basic={basic}
          population={population}
          comparingWith={comparingWith}
          className={classes.graph}
        />
      ))}
    </div>
  );
}
Example #19
Source File: SendModal.js    From akashlytics-deploy with GNU General Public License v3.0 4 votes vote down vote up
SendModal = ({ onClose, onSendTransaction }) => {
  const classes = useStyles();
  const formRef = useRef();
  const [isBalanceClicked, setIsBalanceClicked] = useState(false);
  const [error, setError] = useState("");
  const { balance } = useWallet();
  const {
    handleSubmit,
    control,
    formState: { errors },
    watch,
    setValue,
    clearErrors
  } = useForm({
    defaultValues: {
      recipient: "",
      sendAmount: 0
    }
  });
  const { recipient } = watch();

  const onBalanceClick = () => {
    setIsBalanceClicked((prev) => !prev);
    setError("");
    clearErrors();
    setValue("sendAmount", uaktToAKT(balance - txFeeBuffer, 6));
  };

  const onSubmit = ({ sendAmount }) => {
    clearErrors();
    const amount = aktToUakt(sendAmount);

    if (!recipient) {
      setError(`You must set a recipient.`);
      return;
    }

    if (amount > balance) {
      setError(`You can't send more than you currently have in your balance. Current balance is: ${uaktToAKT(amount, 6)}AKT.`);
      return;
    }

    onSendTransaction(recipient.trim(), amount);
  };

  const onContinueClick = (event) => {
    event.preventDefault();
    formRef.current.dispatchEvent(new Event("submit", { cancelable: true, bubbles: true }));
  };

  return (
    <Dialog maxWidth="xs" fullWidth aria-labelledby="send-transaction-dialog-title" open={true} onClose={onClose}>
      <DialogTitle id="send-transaction-dialog-title">Send tokens</DialogTitle>
      <DialogContent dividers className={classes.dialogContent}>
        <form onSubmit={handleSubmit(onSubmit)} ref={formRef}>
          <FormControl error={!errors.recipient} className={classes.formControl} fullWidth>
            <Controller
              control={control}
              name="recipient"
              rules={{
                required: true
              }}
              render={({ fieldState, field }) => {
                const helperText = "Recipient is required.";

                return (
                  <TextField
                    {...field}
                    type="text"
                    variant="outlined"
                    label="Recipient"
                    error={!!fieldState.invalid}
                    helperText={fieldState.invalid && helperText}
                    className={classes.formValue}
                  />
                );
              }}
            />
          </FormControl>

          <Box marginBottom=".5rem" marginTop=".5rem" textAlign="right">
            <LinkTo onClick={() => onBalanceClick()}>Balance: {uaktToAKT(balance, 6)} AKT</LinkTo>
          </Box>

          <FormControl error={!errors.sendAmount} className={classes.formControl} fullWidth>
            <Controller
              control={control}
              name="sendAmount"
              rules={{
                required: true,
                validate: (value) => value > 0 && value < balance
              }}
              render={({ fieldState, field }) => {
                const helperText = fieldState.error?.type === "validate" ? "Invalid amount." : "Amount is required.";

                return (
                  <TextField
                    {...field}
                    type="number"
                    variant="outlined"
                    label="Amount"
                    autoFocus
                    error={!!fieldState.invalid}
                    helperText={fieldState.invalid && helperText}
                    className={classes.formValue}
                    inputProps={{ min: 0, step: 0.000001, max: uaktToAKT(balance - txFeeBuffer, 6) }}
                    InputProps={{
                      startAdornment: <InputAdornment position="start">AKT</InputAdornment>,
                      endAdornment: isBalanceClicked && (
                        <InputAdornment position="end">
                          <Chip label="MAX" size="small" color="primary" />
                        </InputAdornment>
                      )
                    }}
                    disabled={isBalanceClicked}
                  />
                );
              }}
            />
          </FormControl>
          {error && (
            <Alert severity="warning" className={classes.alert}>
              {error}
            </Alert>
          )}
        </form>
      </DialogContent>
      <DialogActions className={classes.dialogActions}>
        <Button onClick={onClose}>Cancel</Button>
        <Button onClick={onContinueClick} disabled={!!errors.sendAmount || !!errors.recipient} variant="contained" color="primary">
          Continue
        </Button>
      </DialogActions>
    </Dialog>
  );
}
Example #20
Source File: GeneralSkills.js    From resumeker-fe with MIT License 4 votes vote down vote up
function GeneralSkills(props) {
  const { data } = useQuery(DRAFT_ID);
  const [info, setInfo] = useState({
    draftID: "",
    skill: "",
    id: Date.now(),
  });
  const [activeStep, setActiveStep] = useState(6);
  //Instantiate useMutation Hook / Creates tuple with 1st var being actual
  //call function, and 2nd destructured variable being return data and tracking
  const [addSkill, { loading, error }] = useMutation(ADD_SKILL_MUTATION, {
    onCompleted(data) {
      console.log(data, "\n Add General Skill Response");
    },
  });
  const classes = useStyles();

  const addingData = () => {
    if (info.skill.length > 0) {
      props.addGeneralSkill(info);
      //Apollo useMutation API call to send data to backend
      addSkill({
        variables: {
          input: {
            draftID: localStorage.getItem("draftID"),
            skillType: "Qualitative",
            name: info.skill,
          },
        },
      });
    }
  };

  const nextPage = (event) => {
    event.preventDefault();
    addingData();
    props.setActiveStep((prevActiveStep) => prevActiveStep + 1);
    props.history.push("/form/languages");
  };
  const anotherSkill = (event) => {
    event.preventDefault();
    addingData();
    setInfo({
      ...info,
      skill: "",
      id: Date.now(),
    });
  };
  const onChange = (event) => {
    event.preventDefault();
    setInfo({ ...info, [event.target.name]: event.target.value });
  };
  const handleDelete = (skillToDelete) => (event) => {
    event.preventDefault();
    props.removeGeneralSkill(skillToDelete);
    setInfo({ ...info });
  };
  return (
    <div>
      <Grid container componet="main" className={classes.root}>
        <CssBaseline />
        <TipsLayout tips={Tip()} />
        <Grid item xs={12} sm={8} md={9} component={Paper} elevation={6} square>
          <MobileStepper
            variant="progress"
            steps={8}
            position="static"
            activeStep={props.activeStep}
            className={classes.progress}
          />
          <div className={classes.paper}>
            <Typography component="h1" variant="h5">
              Tell us about some of your other skills that didn't quite make it
              into the technical section!
            </Typography>
            <Typography
              color="textSecondary"
              component="h5"
              variant="subtitle2"
            >
              (Time Management, Critical Thinking, Teamwork, Problem Solving,
              Comunication, etc)
            </Typography>
            <form
              className={classes.form}
              onSubmit={anotherSkill}
              id="generalSkillsForm"
            >
              <SingleFieldFormTemplate
                onChange={onChange}
                info={info.skill}
                anotherOne={(e) => anotherSkill(e)}
                name="skill"
                label="General Skill"
              />
              <Grid className={classes.skillContainer}>
                <Paper
                  component="ul"
                  square="true"
                  className={classes.chipContainer}
                >
                  <Chip
                    label="Your Skills:"
                    className={classes.chip}
                    color="primary"
                  />
                  {props.resumeData.generalSkills.map((data) => {
                    return (
                      <li key={data.id} className="listOfGeneralSkills">
                        <Chip
                          label={data.skill}
                          onDelete={handleDelete(data)}
                          className={classes.chip}
                        />
                      </li>
                    );
                  })}
                </Paper>
              </Grid>
              <Grid className={classes.buttonContainer}>
                <Button
                  type="button"
                  fullWidth
                  variant="outlined"
                  color="primary"
                  id="previous_techSkills"
                  className={`${classes.previousButton} singlePageButton`}
                  onClick={() => {
                    props.setActiveStep((prevActiveStep) => prevActiveStep - 1);
                    props.history.push("/form/techskills");
                  }}
                >
                  Previous Form
                </Button>
                <Button
                  type="button"
                  fullWidth
                  variant="contained"
                  color="primary"
                  id="next_languages"
                  className={`${classes.nextButton} singlePageButton`}
                  onClick={(e) => nextPage(e)}
                >
                  Next Form
                </Button>
              </Grid>
            </form>
          </div>
        </Grid>
      </Grid>
      <button onClick={() => nextPage()}>Next Page</button>
    </div>
  );
}
Example #21
Source File: Discussion.js    From app with MIT License 4 votes vote down vote up
function CommentList({ requestId }) {
  const classes = useStyles();
  const firestore = useFirestore();
  const [retries, setRetries] = useState(0);
  const { showError } = useNotifications();

  // This is used to trigger the snapshot subscription after confirming that the user
  // has permission to access the contact info.
  const [query, setQuery] = useState(null);
  const [commentDocs, setCommentDocs] = useState([]);

  // Because of timing issues, this component will likely get run before the server has applied
  // the requested document access resulting in almost a guranteed permission-denied error. So,
  // we use this effect to monitor for permission-denied until the change has propagated, at which
  // point, we do the actual doc subscription (next useEffect);
  useEffect(() => {
    async function getData() {
      try {
        const dataQuery = firestore
          .collection(`${REQUESTS_DISCUSSIONS_COLLECTION}`)
          .where('requestId', '==', requestId)
          .orderBy('createdAt', 'asc');
        // Call it once because this will throw the permission exception.
        await dataQuery.get();
        setQuery(dataQuery); // Setting this will trigger the subscription useEffect.
      } catch (err) {
        // We only try reloading if insufficient permissions.
        if (err.code !== 'permission-denied') {
          throw err;
        }
        if (retries >= 25) {
          // setAccessFailed(true);
          showError(
            'Failed to get contact info access, please try again later.',
          );
        } else {
          window.setTimeout(() => {
            setRetries(retries + 1);
          }, 1000);
        }
      }
    }
    getData();
  }, [retries, firestore, requestId, showError]);

  // Once the previous useEffect verifies that the user has access then this one does the actual
  // document subscription.
  useEffect(() => {
    if (!query) return undefined;
    const unsub = query.onSnapshot((querySnap) => {
      setCommentDocs(querySnap.docs);
    });
    return unsub;
  }, [query]);

  // const querySnapshot = useFirestoreCollection(
  //   firestore
  //     .collection(`${REQUESTS_DISCUSSIONS_COLLECTION}`)
  //     .where('requestId', '==', requestId)
  //     .orderBy('createdAt', 'asc'),
  // );

  if (!commentDocs.length) {
    return (
      <Box color="text.disabled">
        <Typography
          variant="body2"
          className={classes.noComments}
          data-test="no-comments">
          No comments yet.
        </Typography>
        <Divider className={classes.divider} />
      </Box>
    );
  }

  return (
    <List>
      {commentDocs.map(
        (docSnap) =>
          // When new comment is added locally, the createdAt can be the serverTimestamp() value.
          // So, we wait on rendering until any new snapshot has finished writing.
          !docSnap.metadata.hasPendingWrites && (
            <ListItem
              key={docSnap.id}
              divider
              alignItems="flex-start"
              data-test="private-comment">
              <ListItemAvatar>
                <Avatar>{docSnap.get('author.firstName').slice(0, 1)}</Avatar>
              </ListItemAvatar>
              <ListItemText
                disableTypography
                primary={
                  <Typography variant="subtitle2">
                    {docSnap.get('author.firstName')} &ndash;{' '}
                    <Typography
                      variant="body2"
                      display="inline"
                      color="textSecondary">
                      {format(docSnap.get('createdAt').toDate(), 'p - PPPP')}
                    </Typography>{' '}
                    {docSnap.get('kind') !== 1 && (
                      <Chip
                        variant="outlined"
                        size="small"
                        icon={kindMap[docSnap.get('kind')].icon}
                        label={kindMap[docSnap.get('kind')].shortDescription}
                      />
                    )}
                  </Typography>
                }
                secondary={docSnap
                  .get('content')
                  .split('\n')
                  .map((content, key) => (
                    // eslint-disable-next-line react/no-array-index-key
                    <Typography variant="body1" key={key} gutterBottom>
                      {content}
                    </Typography>
                  ))}
              />
            </ListItem>
          ),
      )}
    </List>
  );
}
Example #22
Source File: MetaColInfo.js    From Designer-Client with GNU General Public License v3.0 4 votes vote down vote up
export function MetaColInfo(props) {
  const classes = useStyles();
  const [col, setCol] = useState({...props.col});
  const formHeaders = props.formHeaders;

  const getType = (val) => {
    switch (val) {
      case "varchar":
        return "text";
      default:
        return val;
    }
  };

  const getTypeLength = (type) => {
    const parsedType = getType(type);
    if (TypeLengthMap[type]) {
      return TypeLengthMap[type];
    }

    return "";
  }

  const getFormat = (type) => {
    switch (type) {
      case "datetime":
        return "yyyy-MM-dd HH:mm:ss";
      case "date":
        return "yyyy-MM-dd";
      case "time":
        return "HH:mm:ss";
      default:
        return "";
    }
  }

  const isDateType = (type) => {
    return ["datetime", "date", "time"].indexOf(type) < 0;
  }

  const handleChange = (e) => {
    const updatedCol = {
      ...col,
      [e.target.name]: e.target.type === "checkbox" ? e.target.checked : e.target.value,
    };

    setCol(updatedCol);
  };

  return (
    <Accordion>
      <AccordionSummary
        expandIcon={<ExpandMoreIcon />}
        aria-controls={`column${col.id} - ${col.columnName}`}
        id={`column-${col.id}`}        
      >
        <div className={classes.headerWrap}>
          <Typography className={classes.heading}>
            {col.columnName}
          </Typography>
          <div>
            {col.type && 
              <Chip size="small" label={`Type: ${col.type}`} variant="outlined" />
            }
          </div>
        </div>        
      </AccordionSummary>
      <AccordionDetails className={classes.formWrap}>
        <FormControl className={classes.formControl}>
          <InputLabel
            htmlFor={`meta-${col.id}-input-originName`}
            className="label"
          >
            {formHeaders[0].name}
          </InputLabel>
          <Input
            id={`meta-${col.id}-input-originName`}
            className="form"
            name="originName"
            value={col.originalColumnName}
            disabled={true}
          />
        </FormControl>
        <FormControl className={classes.formControl}>
          <InputLabel
            htmlFor={`meta-${col.id}-input-columnName`}
            className="label"
          >
            {formHeaders[1].name}
          </InputLabel>
          <Input
            id={`meta-${col.id}-input-columnName`}
            className="form"
            name="columnName"
            value={col.columnName}
            onChange={handleChange}
          />
          <FormHelperText className="helpText">
            {formHeaders[1].tooltip}
          </FormHelperText>
        </FormControl>
        <FormControl className={classes.formControl}>
          <InputLabel id={`label-meta-${col.id}-input-type`} className="label">
            {formHeaders[2].name}
          </InputLabel>
          <Select
            labelId={`label-meta-${col.id}-input-type`}
            id={`meta-${col.id}-input-type`}
            name="type"
            value={getType(col.type)}
            className="form"
            onChange={handleChange}
          >
            <MenuItem value={"int"}>숫자(정수)</MenuItem>
            <MenuItem value={"double"}>숫자(부동소수)</MenuItem>
            <MenuItem value={"text"}>문자</MenuItem>
            <MenuItem value={"datetime"}>날짜(시간포함)</MenuItem>
            <MenuItem value={"date"}>날짜(시간 미포함)</MenuItem>
            <MenuItem value={"time"}>시간(시간 미포함)</MenuItem>
          </Select>
        </FormControl>

        {isDateType(col.type) ? 
          <FormControl className={classes.formControl}>
            <InputLabel htmlFor={`meta-${col.id}-input-length`} className="label">
              {formHeaders[3].name}
            </InputLabel>
            <Input
              id={`meta-${col.id}-input-length`}
              value={col.length || getTypeLength(col.type)}
              name="length"
              className="form"
              onChange={handleChange}
            />
          </FormControl>
          :
          <FormControl className={classes.formControl}>
            <InputLabel htmlFor={`meta-${col.id}-input-format`} className="label">
              {formHeaders[4].name}
            </InputLabel>
            <Input
              id={`meta-${col.id}-input-format`}
              value={col.format || getFormat(col.type)}
              name="format"
              className="form"
              onChange={handleChange}
            />
            <FormHelperText className="helpText">
              {formHeaders[4].tooltip}
            </FormHelperText>
          </FormControl>
        }

        <FormControlLabel
          className={`${classes.formControl} options`}
          control={
            <Checkbox
              id={`meta-${col.id}-input-nullable`}
              checked={col.isNullable}
              name="isNullable"
              onChange={handleChange}
              color="primary"
            />
          }
          label={
            <Typography style={{ fontSize: "0.875rem" }}>빈값 허용</Typography>
          }
        />
        <FormControlLabel
          className={`${classes.formControl} options`}
          control={
            <Checkbox
              id={`meta-${col.id}-input-unique`}
              checked={col.isUnique}
              name="isUnique"
              onChange={handleChange}
              color="primary"
            />
          }
          label={
            <Typography style={{ fontSize: "0.875rem" }}>고유값</Typography>
          }
        />
        <FormControlLabel
          className={`${classes.formControl} options`}
          control={
            <Checkbox
              id={`meta-${col.id}-input-hidden`}
              checked={col.isHidden}
              name="isHidden"
              onChange={handleChange}
              color="primary"
            />
          }
          label={
            <Typography style={{ fontSize: "0.875rem" }}>숨김(미제공)</Typography>
          }
        />
      </AccordionDetails>
    </Accordion>
  )
}
Example #23
Source File: CaptureMatchingView.js    From treetracker-admin-client with GNU Affero General Public License v3.0 4 votes vote down vote up
function CaptureMatchingView() {
  const initialFilter = {
    startDate: '',
    endDate: '',
    stakeholderUUID: null,
  };

  const classes = useStyle();
  const appContext = useContext(AppContext);
  const matchingToolContext = useContext(MatchingToolContext);
  const [captureImage, setCaptureImage] = useState(null);
  const [currentPage, setCurrentPage] = useState(1);
  const [loading, setLoading] = useState(false);
  const [candidateImgData, setCandidateImgData] = useState([]);
  const [noOfPages, setNoOfPages] = useState(null); //for pagination
  const [imgCount, setImgCount] = useState(null); //for header icon
  const [treesCount, setTreesCount] = useState(0);
  const [startDate, setStartDate] = useState('');
  const [endDate, setEndDate] = useState('');
  const [organizationId, setOrganizationId] = useState(null);
  const [stakeholderUUID, setStakeholderUUID] = useState(null);
  const [filter, setFilter] = useState(initialFilter);
  const [growerAccount, setGrowerAccount] = useState({});
  // To get total tree count on candidate capture image icon
  // const treesCount = candidateImgData.length;
  const [screenWidth, setScreenWidth] = useState(window.innerWidth);
  const resizeWindow = useCallback(() => {
    setScreenWidth(window.innerWidth);
  }, []);

  useEffect(() => {
    window.addEventListener('resize', resizeWindow);
    return () => {
      window.removeEventListener('resize', resizeWindow);
    };
  }, [resizeWindow]);

  async function fetchCandidateTrees(captureId, abortController) {
    const data = await api.fetchCandidateTrees(captureId, abortController);
    if (data) {
      setCandidateImgData(data.matches);
      setTreesCount(data.matches.length);
      setLoading(false);
    }
  }

  async function clean() {
    setCandidateImgData([]);
    setTreesCount(0);
    setCaptureImage(null);
    setTreesCount(0);
    setImgCount(null);
    // setCurrentPage(1);
    // setNoOfPages(null);
  }

  async function fetchCaptures(currentPage, abortController) {
    clean();
    setLoading(true);
    // log.debug('fetchCaptures filter', filter);
    const filterParameters = {
      captured_at_start_date: filter.startDate,
      captured_at_end_date: filter.endDate,
      'organization_ids[]': filter.stakeholderUUID && [filter.stakeholderUUID],
    };
    // log.debug('fetchCaptures filterParameters', filterParameters);
    const data = await api.fetchCapturesToMatch(
      currentPage,
      abortController,
      filterParameters
    );
    // log.debug('fetchCptures data', currentPage, data);
    if (data?.captures?.length > 0) {
      setCaptureImage(data.captures[0]);
      setNoOfPages(data.count);
      setImgCount(data.count);
    } else {
      setLoading(false);
      setNoOfPages(0);
      setImgCount(0);
      log.warn('no data:', data);
    }
  }

  async function loadGrowerInfo() {
    if (captureImage) {
      // log.warn('loadGrowerInfo...');
      if (captureImage.grower_account_id) {
        const data = await api.getGrowerAccountById(
          captureImage.grower_account_id
        );
        setGrowerAccount(data);
      } else {
        log.warn('No grower account id found');
      }
    }
  }

  useEffect(() => {
    document.title = `Capture Matching - ${documentTitle}`;
  }, []);

  useEffect(() => {
    const abortController = new AbortController();
    fetchCaptures(currentPage, abortController);
    return () => abortController.abort();
  }, [currentPage, filter]);

  useEffect(() => {
    if (currentPage <= 0 || currentPage > noOfPages) {
      setCurrentPage(1);
    }
  }, [noOfPages, currentPage]);

  useEffect(() => {
    const abortController = new AbortController();
    if (captureImage) {
      const captureId = captureImage.id;
      fetchCandidateTrees(captureId, abortController);
      // load grower info
      loadGrowerInfo();
    }
    return () => abortController.abort();
  }, [captureImage]);

  // Capture Image Pagination function
  const handleChange = (e, value) => {
    setCurrentPage(value);
  };

  // Same Tree Capture function
  const sameTreeHandler = async (treeId) => {
    const captureId = captureImage.id;
    // log.debug('captureId treeId', captureId, treeId);
    await fetch(`${CAPTURE_API}/captures/${captureId}`, {
      method: 'PATCH',
      headers: {
        'content-type': 'application/json',
        // Authorization: session.token,
      },
      body: JSON.stringify({
        tree_id: treeId,
      }),
    });

    // make sure new captures are loaded by updating page or if it's the first page reloading directly
    if (currentPage === 1) {
      fetchCaptures(currentPage);
    } else {
      setCurrentPage((page) => page + 1);
    }
  };

  // Skip button
  const handleSkip = () => {
    setCurrentPage((page) => page + 1);
  };

  function handleStartDateChange(e) {
    setStartDate(e.target.value);
  }

  function handleEndDateChange(e) {
    setEndDate(e.target.value);
  }

  function handleFilterSubmit() {
    log.debug('filter submit -----> ', organizationId, stakeholderUUID);
    setFilter({
      startDate,
      endDate,
      stakeholderUUID,
    });
    matchingToolContext.handleFilterToggle();
  }

  function handleFilterReset() {
    setFilter(initialFilter);
    matchingToolContext.handleFilterToggle();
  }

  // components
  function currentCaptureNumber(text, icon, count, tooltip) {
    return (
      <Box>
        <Paper elevation={3} className={classes.currentNumberBox1}>
          <Box className={classes.currentNumberBox2}>
            <Box>
              <Box className={classes.currentNumberBox3}>{icon}</Box>
            </Box>
            <Box>
              <Box className={classes.currentNumberBox4}>
                <Typography
                  variant="h6"
                  className={`${classes.currentNumberText} ${classes.currentNumberBold}`}
                >
                  {count}
                </Typography>
                {tooltip && (
                  <Tooltip placement="right-start" title={tooltip}>
                    <QuestionMarkIcon />
                  </Tooltip>
                )}
              </Box>
              <Typography variant="body1" className={classes.currentNumberText}>
                {text}
              </Typography>
            </Box>
          </Box>
        </Paper>
      </Box>
    );
  }

  const CaptureHeader = (
    <Box>
      <Box>
        <Grid container className={classes.currentHeaderBox1}>
          {currentCaptureNumber(
            `Unmatched Capture${(imgCount !== 1 && 's') || ''}`,
            <PhotoCameraOutlinedIcon
              className={classes.currentHeaderCaptureImgIcon}
            />,
            imgCount,
            ''
          )}
          <Box className={classes.currentHeaderBox2}>
            <Box>
              {(filter.startDate || filter.endDate) && (
                <Chip
                  label={`${filter.startDate || 'Start Date'} - ${
                    filter.endDate || 'End Date'
                  }`}
                  className={classes.currentHeaderChip}
                  onDelete={() =>
                    setFilter({
                      ...filter,
                      startDate: undefined,
                      endDate: undefined,
                    })
                  }
                />
              )}
              {filter.stakeholderUUID && (
                <Chip
                  label={appContext.orgList.reduce((a, c) => {
                    return c.stakeholder_uuid === filter.stakeholderUUID
                      ? c.name
                      : a;
                  }, '')}
                  className={classes.currentHeaderChip}
                  onDelete={() =>
                    setFilter({
                      ...filter,
                      stakeholderUUID: undefined,
                    })
                  }
                />
              )}
            </Box>
            <IconButton
              onClick={matchingToolContext.handleFilterToggle}
              className={classes.currentHeaderClass1}
            >
              <FilterListIcon htmlColor="#6E6E6E" />
            </IconButton>
            <Pagination
              count={noOfPages}
              page={currentPage}
              onChange={handleChange}
              defaultPage={1}
              size="small"
              siblingCount={0}
            />
          </Box>
        </Grid>
      </Box>
    </Box>
  );

  const CaptureImage = (
    <Box className={classes.captureImageBox1}>
      {CaptureHeader}
      <Box height={16} />
      {!loading && !captureImage && (
        //captureImage && treesCount === 0 && (
        <Box>
          <Typography variant="h5">No capture found.</Typography>
        </Box>
      )}
      {captureImage && (
        <Paper
          elevation={4}
          key={`capture_${captureImage.id}`}
          className={classes.captureImageContainerBox}
        >
          <Box className={classes.captureImageHeaderBox}>
            <Box className={classes.box2}>
              <Tooltip title={captureImage.id} interactive>
                <Typography variant="h5">
                  Capture {(captureImage.id + '').substring(0, 10) + '...'}
                </Typography>
              </Tooltip>
              <Box className={classes.captureImageCaptureInfo}>
                <Box className={classes.captureImageBox3}>
                  <AccessTimeIcon />
                  <Typography variant="body1">
                    {getDateTimeStringLocale(captureImage.created_at)}
                  </Typography>
                </Box>
                <Box className={classes.captureImageBox3}>
                  <LocationOnOutlinedIcon
                    style={{
                      cursor: 'pointer',
                    }}
                    onClick={() => {
                      window.open(
                        `https://www.google.com/maps/search/?api=1&query=${captureImage.latitude},${captureImage.longitude}`
                      );
                    }}
                  />
                  <Typography variant="body1">
                    <Country
                      lat={captureImage.latitude}
                      lon={captureImage.longitude}
                    />
                  </Typography>
                </Box>
              </Box>
            </Box>

            {!loading && growerAccount && (
              <Box className={classes.growerBox1}>
                <Avatar
                  className={classes.growerAvatar}
                  src={growerAccount.image_url}
                />
                <Box className={classes.growerBox2}>
                  <Typography variant="h5">
                    {growerAccount.first_name}
                  </Typography>
                  <Typography variant="body1">
                    Joined at{' '}
                    {moment(
                      growerAccount.first_registration_at ||
                        growerAccount.created_at
                    ).format('MM/DD/YYYY')}
                  </Typography>
                </Box>
              </Box>
            )}
            {loading && <Box>...</Box>}
            {!loading && !growerAccount && <Box>no grower info</Box>}

            <Button
              variant="text"
              color="primary"
              onClick={handleSkip}
              className={classes.captureImageButton}
            >
              Skip
              <SkipNextIcon />
            </Button>
          </Box>

          <Box className={classes.captureImageImgBox}>
            <OptimizedImage
              key={captureImage.id}
              className={classes.captureImageImgContainer}
              src={captureImage.image_url}
              alt={`Capture ${captureImage.id}`}
              objectFit="contain"
              width={screenWidth * 0.5}
              fixed
              alertWidth="100%"
              alertHeight="30%"
              alertPadding="2rem"
              alertTitleSize="1.6rem"
              alertTextSize="1rem"
            />
          </Box>
        </Paper>
      )}
    </Box>
  );

  return (
    <>
      <Grid
        container
        direction="column"
        style={{
          flexWrap: 'nowrap',
          height: '100%',
          overflow: 'hidden',
        }}
      >
        <Navbar />
        <Box className={classes.container}>
          <Paper elevation={8} className={classes.box1}>
            {CaptureImage}
          </Paper>
          <Box className={classes.box2}>
            <Box className={classes.candidateIconBox}>
              {currentCaptureNumber(
                `Candidate Match${(treesCount !== 1 && 'es') || ''}`,
                <NatureOutlinedIcon className={classes.candidateImgIcon} />,
                treesCount,
                `Any tree within 6m of the capture`
              )}
            </Box>
            <Box height={14} />
            {loading ? null : (
              <CandidateImages
                capture={captureImage}
                candidateImgData={candidateImgData}
                sameTreeHandler={sameTreeHandler}
              />
            )}
            {!loading &&
              captureImage &&
              candidateImgData &&
              candidateImgData.length === 0 && (
                //captureImage && treesCount === 0 && (
                <Box className={classes.noCandidateBox}>
                  <Typography variant="h5">
                    No candidate match found, this capture might be a new tree
                  </Typography>
                </Box>
              )}
          </Box>
        </Box>
        {loading && (
          <AppBar position="fixed" style={{ zIndex: 10000 }}>
            <LinearProgress color="primary" />
          </AppBar>
        )}
      </Grid>
      <Drawer
        anchor="right"
        BackdropProps={{ invisible: false }}
        open={matchingToolContext.isFilterOpen}
      >
        <Grid
          container
          direction="column"
          className={classes.customTableFilterForm}
        >
          {/* start  filter header */}
          <Grid item className={classes.customTableFilterHeader}>
            <Grid container direction="row" justify="space-between">
              <Grid item>
                <Grid container direction="row">
                  <Typography variant="h6">Filter</Typography>
                </Grid>
              </Grid>
              <CloseIcon
                onClick={matchingToolContext.handleFilterToggle}
                className={classes.customTableFilterCloseIcon}
              />
            </Grid>
          </Grid>
          {/* end   filter header */}

          {/* start filter body */}

          <>
            <FormControl
              variant="outlined"
              className={classes.customTableFilterSelectFormControl}
            >
              <TextField
                id="start_date"
                name="start_date"
                value={startDate}
                label="Start Date"
                type="date"
                onChange={handleStartDateChange}
                InputLabelProps={{
                  shrink: true,
                }}
              />
            </FormControl>

            <FormControl
              variant="outlined"
              className={classes.customTableFilterSelectFormControl}
            >
              <TextField
                id="end_date"
                name="end_date"
                label="End Date"
                value={endDate}
                onChange={handleEndDateChange}
                type="date"
                InputLabelProps={{
                  shrink: true,
                }}
              />
            </FormControl>
          </>
          <FormControl
            variant="outlined"
            className={classes.customTableFilterSelectFormControl}
          >
            <SelectOrg
              orgId={organizationId || 'ORGANIZATION_NOT_SET'}
              defaultOrgs={[
                {
                  id: 'ORGANIZATION_NOT_SET',
                  stakeholder_uuid: null,
                  name: 'Not set',
                  value: null,
                },
              ]}
              handleSelection={(org) => {
                setOrganizationId(org.id);
                setStakeholderUUID(org.stakeholder_uuid);
              }}
            />
          </FormControl>

          <Divider
            style={{
              margin: '50px 0 20px 0',
            }}
          />

          <Grid
            container
            direction="column"
            className={classes.customTableFilterActions}
          >
            <Button
              variant="contained"
              color="primary"
              disableElevation
              className={classes.customTableFilterSubmitButton}
              onClick={handleFilterSubmit}
            >
              APPLY
            </Button>
            <Button
              color="primary"
              variant="text"
              onClick={handleFilterReset}
              className={classes.customTableFilterResetButton}
            >
              RESET
            </Button>
          </Grid>
        </Grid>
      </Drawer>
    </>
  );
}
Example #24
Source File: EditEvent.jsx    From archeage-tools with The Unlicense 4 votes vote down vote up
render() {
    const { id, open, onClose, mobile, eventTypes } = this.props;
    const { formData: { name, icon, eventType, description, link, times, disabled }, avatarSelect, editTime, timeData, error, loading } = this.state;

    return (
      <Dialog
        open={open}
        onClose={onClose}
        fullScreen={mobile}
      >
        <AppBar position="static">
          <Toolbar variant="dense">
            <Typography className="title-text">{id ? 'Edit' : 'New'} Event</Typography>
            <IconButton color="inherit" aria-label="Close" onClick={onClose}>
              <CloseIcon />
            </IconButton>
          </Toolbar>
        </AppBar>
        <DialogContent>
          <form autoComplete="off" onSubmit={this.handleSubmit} ref={this.form}>
            <div className="event-form">
              <div className="avatar-opt">
                <Avatar src={icon ? `/images/event/${icon}.png` : null} onClick={this.toggleAvatar} />
                <Typography>{icon || 'Select an icon.'}</Typography>
              </div>
              <TextField
                required
                id="event-name"
                label="Event Name"
                value={name || ''}
                onChange={(e) => this.handleChange('name', e.target.value)}
              />
              <FormControl required>
                <InputLabel id="event-type-select">Type</InputLabel>
                <Select
                  labelId="event-type-select"
                  id="event-type"
                  value={eventType || ''}
                  onChange={(e) => this.handleChange('eventType', e.target.value)}
                >
                  {Object.values(eventTypes).map(type => (
                    <MenuItem
                      value={type.id}
                      key={`etype-${type.id}`}
                    >
                      {type.name}
                    </MenuItem>
                  ))}
                </Select>
              </FormControl>
              <TextField
                id="event-desc"
                label="Description"
                value={description || ''}
                onChange={(e) => this.handleChange('description', e.target.value)}
                multiline
              />
              <TextField
                id="event-link"
                label="Link"
                value={link || ''}
                onChange={(e) => this.handleChange('link', e.target.value)}
              />
              <div>
                <FormControlLabel
                  control={
                    <Checkbox
                      checked={disabled || false}
                      onChange={(_, disabled) => this.handleChange('disabled', disabled)}
                      name="disabled"
                    />}
                  label="Disabled"
                />
              </div>
              <div className="times">
                <Typography>Times</Typography>
                <div className="chips">
                  {(times || []).map((time, timeId) => (
                    <Chip
                      key={`time-${timeId}`}
                      icon={<Avatar>{time.region || 'GT'}</Avatar>}
                      label={`${time.time} ${time.days.length > 0 && time.days.length < 7
                        ? time.days.map(day => DAY_ABBR[day]).join('') : ''}`}
                      onClick={this.editTime(timeId)}
                      onDelete={this.deleteTime(timeId)}
                      variant="outlined"
                      color={editTime === timeId ? 'primary' : 'secondary'}
                    />
                  ))}
                  {editTime === false &&
                  <IconButton onClick={this.editTime()}>
                    <AddIcon />
                  </IconButton>}
                </div>
              </div>
            </div>
          </form>
          {editTime !== false &&
          <Paper elevation={3}>
            <form autoComplete="off" onSubmit={this.saveTime} className="time-form">
              <Typography>{editTime === true ? 'Add Time' : 'Edit Time'}</Typography>
              <FormControl
                style={{ width: 75 }}
                disabled={Boolean(timeData.gameTime)}
              >
                <InputLabel id="region-label" shrink>Region</InputLabel>
                <Select
                  labelId="region-label"
                  id="region"
                  value={timeData.region || ''}
                  onChange={(e) => this.handleChangeTime('region', e.target.value)}
                >
                  {[null, ...Object.values(REGIONS)].map(region => (
                    <MenuItem
                      value={region}
                      key={`region-${region}`}
                    >
                      {region || 'None'}
                    </MenuItem>
                  ))}
                </Select>
              </FormControl>
              <TextField
                id="start-time"
                label="Start Time"
                margin="dense"
                type="time"
                required
                value={timeData.time || ''}
                onChange={(e) => this.handleChangeTime('time', this.handleTime(e))}
                InputLabelProps={{
                  shrink: true,
                }}
                inputProps={{
                  step: 900,
                }}
              />
              <TextField
                id="duration"
                label="Duration"
                margin="dense"
                type="time"
                value={timeData.duration || ''}
                onChange={(e) => this.handleChangeTime('duration', this.handleTime(e))}
                InputLabelProps={{
                  shrink: true,
                }}
                inputProps={{
                  step: 900,
                }}
              />
              <TextField
                id="in-game-time"
                label="Game Time?"
                margin="dense"
                type="time"
                value={timeData.gameTime || ''}
                onChange={(e) => {
                  const gameTime = this.handleTime(e);
                  this.handleChangeTime('gameTime', gameTime, () => {
                    if (gameTime) {
                      this.handleChangeTime('region', null);
                    }
                  });
                }}
                InputLabelProps={{
                  shrink: true,
                }}
                inputProps={{
                  step: 900,
                }}
              />
              <TextField
                id="time-name"
                label="Name"
                margin="dense"
                value={timeData.name || ''}
                onChange={(e) => this.handleChangeTime('name', e.target.value)}
                InputLabelProps={{
                  shrink: true,
                }}
                placeholder={`${name || 'Event Name'}: ...`}
              />
              <TextField
                className="start-message"
                id="time-message"
                label="Start Message"
                margin="dense"
                value={timeData.startMessage || ''}
                onChange={(e) => this.handleChangeTime('startMessage', e.target.value)}
                InputLabelProps={{
                  shrink: true,
                }}
                placeholder="Alternate message for when this event starts."
              />
              <TextField
                id="reminder-time"
                label="Reminder Time"
                margin="dense"
                type="time"
                value={timeData.reminderTime || ''}
                onChange={(e) => this.handleChangeTime('reminderTime', this.handleTime(e))}
                InputLabelProps={{
                  shrink: true,
                }}
                inputProps={{
                  step: 900,
                }}
              />
              <TextField
                className="start-message"
                id="time-reminder-message"
                label="Reminder Message"
                margin="dense"
                value={timeData.reminderMessage || ''}
                onChange={(e) => this.handleChangeTime('reminderMessage', e.target.value)}
                InputLabelProps={{
                  shrink: true,
                }}
                placeholder="Alternate message for when this event is starting soon."
              />
              <FormControl className="day-select">
                <InputLabel id="time-days-label">Days</InputLabel>
                <Select
                  labelId="time-days-label"
                  id="time-days"
                  multiple
                  value={timeData.days || []}
                  onChange={(e) => this.handleChangeTime('days', e.target.value)}
                  input={<Input id="select-multiple-chip" />}
                  renderValue={(selected) => (
                    <div className="day-chips">
                      {selected.map((value) => (
                        <Chip key={value} label={DAY[value]} className="day-chip" />
                      ))}
                    </div>
                  )}
                >
                  {Object.entries(DAY).map(([key, name]) => (
                    <MenuItem key={key} value={key} className="day-item">
                      {name}
                    </MenuItem>
                  ))}
                </Select>
              </FormControl>
              <IconButton type="submit"><CheckIcon /></IconButton>
              <IconButton onClick={this.editTime(false)}><CloseIcon /></IconButton>
            </form>
          </Paper>}
          <Popover
            anchorOrigin={{
              vertical: 'top',
              horizontal: 'left',
            }}
            transformOrigin={{
              vertical: 'top',
              horizontal: 'left',
            }}
            anchorEl={avatarSelect}
            open={Boolean(avatarSelect)}
            elevation={2}
            onClose={() => this.toggleAvatar()}
          >
            <div className="avatar-select">
              {Object.entries(EventIcon).sort(sortBy(0)).map(([key, url]) => (
                <Tooltip title={getIconName(url)} key={key}>
                  <Avatar
                    src={url}
                    onClick={() => {
                      this.handleChange('icon', getIconName(url));
                      this.toggleAvatar();
                    }}
                  />
                </Tooltip>
              ))}
            </div>
          </Popover>
          {error &&
          <Box color="error.main">
            <Typography>{error}</Typography>
          </Box>}
          <DialogActions>
            <Button onClick={onClose}>
              Cancel
            </Button>
            <Button
              color="primary"
              onClick={() => this.form.current.dispatchEvent(new Event('submit'))}
              disabled={loading}
            >
              Save
            </Button>
          </DialogActions>
        </DialogContent>
      </Dialog>
    );
  }
Example #25
Source File: AnswerForm.js    From stack-underflow with MIT License 4 votes vote down vote up
AnswerForm = ({ quesId, tags }) => {
  const classes = useQuesPageStyles();
  const { user } = useAuthContext();
  const { clearEdit, notify } = useStateContext();
  const { register, handleSubmit, reset, errors } = useForm({
    mode: 'onChange',
    resolver: yupResolver(validationSchema),
  });

  const [addAnswer, { loading }] = useMutation(POST_ANSWER, {
    onError: (err) => {
      notify(getErrorMsg(err), 'error');
    },
  });

  const postAnswer = ({ answerBody }) => {
    addAnswer({
      variables: { quesId, body: answerBody },
      update: (proxy, { data }) => {
        reset();

        const dataInCache = proxy.readQuery({
          query: VIEW_QUESTION,
          variables: { quesId },
        });

        const updatedData = {
          ...dataInCache.viewQuestion,
          answers: data.postAnswer,
        };

        proxy.writeQuery({
          query: VIEW_QUESTION,
          variables: { quesId },
          data: { viewQuestion: updatedData },
        });

        notify('Answer submitted!');
      },
    });
  };

  return (
    <div className={classes.answerForm}>
      {user && (
        <Typography variant="h6" color="secondary">
          Your Answer
        </Typography>
      )}
      {user && (
        <form onSubmit={handleSubmit(postAnswer)}>
          <TextField
            inputRef={register}
            name="answerBody"
            required
            fullWidth
            type="text"
            placeholder="Enter atleast 30 characters"
            variant="outlined"
            size="small"
            error={'answerBody' in errors}
            helperText={'answerBody' in errors ? errors.answerBody.message : ''}
            multiline
            rows={5}
          />
          <div>
            <Button
              color="primary"
              variant="contained"
              style={{ marginTop: '0.8em' }}
              type="submit"
              disabled={loading}
            >
              Post Your Answer
            </Button>
          </div>
        </form>
      )}
      <div className={classes.footerText}>
        <span>
          Browse other questions tagged{' '}
          {tags.map((t) => (
            <Chip
              key={t}
              label={t}
              variant="outlined"
              color="primary"
              size="small"
              component={RouterLink}
              to={`/tags/${t}`}
              className={classes.footerTag}
              clickable
            />
          ))}
          or{' '}
          {user ? (
            <Link component={RouterLink} to="/ask" onClick={() => clearEdit()}>
              ask your own question.
            </Link>
          ) : (
            <AuthFormModal buttonType="link" />
          )}
        </span>
      </div>
    </div>
  );
}
Example #26
Source File: Card.js    From to-view-list with MIT License 4 votes vote down vote up
Card = ({ entry }) => {
  const {
    id,
    title,
    link,
    description,
    tags,
    type,
    isViewed,
    isStarred,
    createdAt,
    updatedAt,
  } = entry;

  const [{ darkMode }, dispatch] = useEntryContext();
  const history = useHistory();
  const theme = useTheme();
  const isMobile = useMediaQuery(theme.breakpoints.down('xs'));
  const classes = useCardStyles(isViewed, darkMode)();

  const handleStarToggle = async () => {
    try {
      dispatch(toggleStarEntry(id));
      await entryService.star(id);
      notify(
        dispatch,
        `${isStarred ? 'Un-Starred' : 'Starred'} "${title}"!`,
        'success'
      );
    } catch (err) {
      if (err?.response?.data?.error) {
        notify(dispatch, `${err.response.data.error}`, 'error');
      } else {
        notify(dispatch, `${err.message}`, 'error');
      }
    }
  };

  const handleViewToggle = async () => {
    try {
      dispatch(toggleViewEntry(id));
      await entryService.view(id);
      notify(
        dispatch,
        `Marked "${title}" as ${isViewed ? 'Not Viewed' : 'Viewed'}!`,
        'success'
      );
    } catch (err) {
      if (err?.response?.data?.error) {
        notify(dispatch, `${err.response.data.error}`, 'error');
      } else {
        notify(dispatch, `${err.message}`, 'error');
      }
    }
  };

  const handleTagFilter = (tag) => {
    dispatch(setTagFilter(tag));
  };

  const handleEdit = () => {
    dispatch(setEditValues(entry));
    history.push('/add_update');
  };

  const handleDelete = async () => {
    try {
      dispatch(removeEntry(id));
      await entryService.remove(id);
      notify(dispatch, `Successfully deleted "${title}"!`, 'success');
    } catch (err) {
      if (err?.response?.data?.error) {
        notify(dispatch, `${err.response.data.error}`, 'error');
      } else {
        notify(dispatch, `${err.message}`, 'error');
      }
    }
  };

  const formattedLink = link.startsWith('http') ? link : `https://${link}`;
  const iconSize = isMobile ? 'small' : 'large';
  const iconStyle = { marginRight: 8 };

  return (
    <Paper className={classes.root} variant="outlined">
      <div className={classes.cardTitle}>
        <Typography variant="h5" className={classes.linkTitle}>
          {type === 'article' ? (
            <WebIcon style={iconStyle} fontSize={iconSize} />
          ) : type === 'video' ? (
            <YouTubeIcon style={iconStyle} fontSize={iconSize} />
          ) : (
            <LineStyleIcon style={iconStyle} fontSize={iconSize} />
          )}
          {title}
        </Typography>
        <div className={classes.endButtons}>
          {!isMobile ? (
            <>
              <Button
                onClick={handleEdit}
                startIcon={<EditIcon />}
                className={classes.edit}
              >
                Edit
              </Button>
              <DeleteDialog
                handleDelete={handleDelete}
                title={title}
                isMobile={isMobile}
              />
            </>
          ) : (
            <>
              <IconButton onClick={handleEdit} className={classes.edit}>
                <EditIcon />
              </IconButton>
              <DeleteDialog
                handleDelete={handleDelete}
                title={title}
                isMobile={isMobile}
              />
            </>
          )}
          <FormControlLabel
            control={
              <Checkbox
                checked={isStarred}
                icon={<StarBorderIcon className={classes.starIcon} />}
                checkedIcon={<StarIcon className={classes.starIcon} />}
                className={classes.star}
              />
            }
            label={isMobile ? '' : isStarred ? 'Starred!' : 'Star it'}
            onChange={handleStarToggle}
            className={classes.starButton}
          />
          <FormControlLabel
            control={
              <Checkbox
                checked={isViewed}
                icon={<VisibilityOutlinedIcon className={classes.viewIcon} />}
                checkedIcon={<VisibilityIcon className={classes.viewIcon} />}
                className={classes.view}
              />
            }
            label={isMobile ? '' : isViewed ? 'Viewed!' : 'Mark as viewed'}
            onChange={handleViewToggle}
            className={classes.viewButton}
          />
        </div>
      </div>
      <Divider />
      <div>
        <Link
          href={formattedLink}
          target="_blank"
          rel="noreferrer"
          variant="h6"
          color="secondary"
          className={classes.link}
        >
          <LinkIcon style={{ marginRight: 8 }} />
          {formattedLink.length > 40
            ? formattedLink.slice(0, 40) + '...'
            : formattedLink}
        </Link>
        <Typography varaint="body1" className={classes.description}>
          {description}
        </Typography>
        {tags.length !== 0 && (
          <div className={classes.tagsGroup}>
            Tags:{' '}
            {tags.map((tag) => (
              <Chip
                key={tag}
                label={tag}
                color="secondary"
                className={classes.tag}
                onClick={() => handleTagFilter(tag)}
              />
            ))}
          </div>
        )}
        <Typography variant="body2" className={classes.addedTime}>
          <Tooltip title={createdAt}>
            <span>
              Added:{' '}
              <TimeAgo datetime={createdAt} className={classes.timestamp} />
            </span>
          </Tooltip>
          {createdAt !== updatedAt ? (
            <Tooltip title={updatedAt}>
              <span>
                {' '}
                | Last modified:{' '}
                <TimeAgo
                  datetime={updatedAt}
                  className={classes.timestamp}
                />{' '}
              </span>
            </Tooltip>
          ) : null}
        </Typography>
      </div>
    </Paper>
  );
}
Example #27
Source File: LatestOrders.js    From EMP with MIT License 4 votes vote down vote up
LatestOrders = () => {
  // const classes = useStyles();
  const [orders] = useState(data);

  return (
    <Card>
      <CardHeader title="Latest Orders" />
      <Divider />
      <PerfectScrollbar>
        <Box minWidth={800}>
          <Table>
            <TableHead>
              <TableRow>
                <TableCell>
                  Order Ref
                </TableCell>
                <TableCell>
                  Customer
                </TableCell>
                <TableCell sortDirection="desc">
                  <Tooltip
                    enterDelay={300}
                    title="Sort"
                  >
                    <TableSortLabel
                      active
                      direction="desc"
                    >
                      Date
                    </TableSortLabel>
                  </Tooltip>
                </TableCell>
                <TableCell>
                  Status
                </TableCell>
              </TableRow>
            </TableHead>
            <TableBody>
              {orders.map((order) => (
                <TableRow
                  hover
                  key={order.id}
                >
                  <TableCell>
                    {order.ref}
                  </TableCell>
                  <TableCell>
                    {order.customer.name}
                  </TableCell>
                  <TableCell>
                    {moment(order.createdAt).format('DD/MM/YYYY')}
                  </TableCell>
                  <TableCell>
                    <Chip
                      color="primary"
                      label={order.status}
                      size="small"
                    />
                  </TableCell>
                </TableRow>
              ))}
            </TableBody>
          </Table>
        </Box>
      </PerfectScrollbar>
      <Box
        display="flex"
        justifyContent="flex-end"
        p={2}
      >
        <Button
          color="primary"
          endIcon={<ArrowRightIcon />}
          size="small"
          variant="text"
        >
          View all
        </Button>
      </Box>
    </Card>
  );
}
Example #28
Source File: SchematicCard.js    From eSim-Cloud with GNU General Public License v3.0 4 votes vote down vote up
// Card displaying overview of onCloud saved schematic.
export default function SchematicCard ({ sch }) {
  const classes = useStyles()
  const dispatch = useDispatch()

  useEffect(() => {
    dispatch(fetchSchematics())
  }, [dispatch])

  // To handle delete schematic snackbar
  const [snacOpen, setSnacOpen] = React.useState(false)

  const handleSnacClick = () => {
    setSnacOpen(true)
  }
  const handleSnacClose = (event, reason) => {
    if (reason === 'clickaway') {
      return
    }
    setSnacOpen(false)
  }
  const clickViewProject = () => {
    const win = window.open()
    win.location.href = '/eda/#/project?save_id=' + sch.save_id + '&version=' + sch.project_version + '&branch=' + sch.project_branch + '&project_id=' + sch.project_id
    win.focus()
  }

  const clickViewLTI = () => {
    const win = window.open()
    win.location.href = `/eda/#/lti?id=${sch.save_id}&version=${sch.version}&branch=${sch.branch}`
  }

  return (
    <>
      {/* User saved Schematic Overview Card */}

      <Card>
        <ButtonBase
          target="_blank"
          component={RouterLink}
          to={sch.lti_id ? `/editor?id=${sch.save_id}&version=${sch.version}&lti_id=${sch.lti_id}&branch=${sch.branch}` : `/editor?id=${sch.save_id}&version=${sch.version}&branch=${sch.branch}`}
          // to={'/editor?id=' + sch.save_id + '&version=' + sch.version + '&branch=' + sch.branch}
          style={{ width: '100%' }}
        >
          <CardActionArea>
            <CardHeader
              title={sch.name}
              subheader={'Created On ' + getDate(sch.create_time)}
              action={sch.project_id && sch.is_reported === true && <Tooltip title='Project is reported!' arrow><ReportProblemIcon style={{ color: 'red' }} /></Tooltip>}
            />
            <CardMedia
              className={classes.media}
              image={sch.base64_image}
              title={sch.name}
            />
            <CardContent>
              <Typography variant="body2" component="p">
                {sch.description}
              </Typography>
              {/* Display updated status */}
              <Typography variant="body2" color="textSecondary" component="p" style={{ margin: '5px 0px 0px 0px' }}>

              </Typography>
            </CardContent>
          </CardActionArea>
        </ButtonBase>
        <CardActions>
          <Chip color='primary' variant='outlined' label={`Updated ${timeSince(sch.save_time)} ago...`} />
          {sch.project_id && <Chip variant='outlined' clickable={true} onClick={clickViewProject} label='Project' />}
          {sch.lti_id && <Chip variant='outlined' clickable={true} onClick={clickViewLTI} label='LTI' />}
          {/* Display create LTI app option  */}
          {!sch.lti_id && <Tooltip title='Create LTI app' placement="bottom" arrow>
            <IconButton
              component={RouterLink}
              color='secondary'
              // style={{ marginLeft: 'auto' }}
              // fontSize="small"
              to={`/lti?id=${sch.save_id}&version=${sch.version}&branch=${sch.branch}`} >
              <ScreenShareRoundedIcon fontSize="small" />
            </IconButton>
          </Tooltip>}
          {/* Display delete option */}
          {!sch.project_id &&
          <Button onClick={() => { handleSnacClick() }}>
            <Tooltip title="Delete" placement="bottom" arrow>
              <DeleteIcon
                color="secondary"
                fontSize="small"
              // style={{ marginLeft: 'auto' }}
              />
            </Tooltip>
          </Button>}
          <SimpleSnackbar open={snacOpen} close={handleSnacClose} sch={sch} confirmation={deleteSchematic} />

          {/* Display share status */}
          <Tooltip
            title={!sch.shared ? 'SHARE OFF' : 'SHARE ON'}
            placement="bottom"
            arrow
          >
            <ShareIcon
              color={!sch.shared ? 'disabled' : 'primary'}
              fontSize="small"
              style={{ marginRight: '10px' }}
            />
          </Tooltip>
        </CardActions>
      </Card>

    </>
  )
}
Example #29
Source File: Projects.js    From gitlab-lint-react with BSD 3-Clause "New" or "Revised" License 4 votes vote down vote up
Projects = () => {
  const classes = useStyles();

  const [page, setPage] = useState(1);
  const [searchInput, setSearchInput] = useState("");
  const handleChange = (event, value) => {
    setPage(value);
    fetchData({ query: { page: value, q: searchInput } });
  };
  const debouncedSearch = useCallback(
    () => debounce((value) => fetchData({ query: { page, q: value } }), 500),
    [page]
  );
  const handleChangeSearch = (value) => {
    setSearchInput(value);
    debouncedSearch(value);
  };
  const [rows, setData] = useState({});
  const [meta, setMeta] = useState({});
  const fetchData = ({ query }) => {
    GitlabLintHttpClient("GET_ALL", { entity: "projects", query: query })
      .then((data) => {
        setData(data.data);
        setMeta(data.meta);
      })
      .catch((err) => console.error(err));
  };

  useEffect(() => {
    fetchData({ query: { page: 1 } });
  }, []);

  if (Object.keys(rows).length === 0 && rows.constructor === Object) {
    return <Loading />;
  }

  return (
    <React.Fragment>
      <div className={classes.header}>
        <Typography variant="h4" paragraph>
          Projects
        </Typography>
        <form noValidate autoComplete="off">
          <Input
            placeholder="Find a project..."
            value={searchInput}
            onChange={(e) => handleChangeSearch(e.target.value)}
          />
        </form>
      </div>
      <List>
        {rows.map((row) => {
          return (
            <ListItem
              button
              component={Link}
              to={`/projects/${row.id}`}
              key={row.id}
            >
              <ListItemText primary={row.path_with_namespace} />
              <div className={classes.levels}>
                {Object.keys(row.rules).map((key, index) => {
                  return (
                    <Tooltip key={key} title={key} placement="top-start">
                      <Chip
                        className={`${classes.level} ${classes[key]}`}
                        label={row.rules[key]}
                        size="small"
                      />
                    </Tooltip>
                  );
                })}
              </div>
            </ListItem>
          );
        })}
      </List>
      <div className={classes.pagination}>
        <Pagination
          boundaryCount={2}
          color="primary"
          count={meta.totalOfPages}
          onChange={handleChange}
          page={page}
          siblingCount={2}
        />
      </div>
    </React.Fragment>
  );
}