semantic-ui-react#Loader JavaScript Examples

The following examples show how to use semantic-ui-react#Loader. 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: LeftRail.jsx    From react-chatengine-demo with MIT License 6 votes vote down vote up
LeftRail = () => {
  const { myChats, createChatClick } = useChat();
  const chatsResolved = useResolved(myChats);

  return (
    <div className="left-rail">
      <RailHeader />
      {chatsResolved ? (
        <>
          {!!myChats.length ? (
            <div className="chat-list-container">
              <ChatList />
            </div>
          ) : (
            <div className="chat-list-container no-chats-yet">
              <h3>No Chats Yet</h3>
            </div>
          )}
          <button className="create-chat-button" onClick={createChatClick}>
            Create Chat
          </button>
        </>
      ) : (
        <div className="chats-loading">
          <Loader active size="huge" />
        </div>
      )}
    </div>
  );
}
Example #2
Source File: Feed.js    From social-network with MIT License 6 votes vote down vote up
render() {
    const { loadingUser, posts, totalPosts } = this.props;
    const hasMore = posts.length === totalPosts ? false : true;
    const feedPosts = posts.map((post) => (
      <Post key={post._id} post={{ ...post, feed: true }} />
    ));

    return loadingUser ? (
      <Dimmer active>
        <Loader />
      </Dimmer>
    ) : (
      <InfiniteScroll
        dataLength={posts.length} //This is important field to render the next data
        next={this.fetchData}
        hasMore={hasMore}
        loader={<h4>Loading...</h4>}
        endMessage={
          <Divider horizontal>
            <Header as="h4">
              <Icon name="eye" />
              Yay! You have seen it all
            </Header>
          </Divider>
        }
      >
        {feedPosts}
      </InfiniteScroll>
    );
  }
Example #3
Source File: PatronOverview.js    From react-invenio-app-ils with MIT License 6 votes vote down vote up
renderStatistic(stat, quantifiableLabel, anchor) {
    const {
      isLoading,
      data: { total },
    } = stat;

    return (
      <Statistic onClick={() => this.scrollTo(anchor)} className="anchored">
        <Statistic.Value>
          {isLoading ? <Loader active inline /> : total}
        </Statistic.Value>
        <Statistic.Label>
          {isLoading ? <>&nbsp;</> : quantifiableLabel(total !== 1)}
        </Statistic.Label>
      </Statistic>
    );
  }
Example #4
Source File: Layout.js    From nextfeathers with Apache License 2.0 6 votes vote down vote up
Layout = (props) => {
  const { user, isReady } = useContext(UserContext);
  const { seoData, pageType, authPage, children } = props;
  const seoDataObj = seoData ? seoData : {};
  const { title, desc, summary, canonical, image, css, js } = seoDataObj;

  const pageWrapperClass = pageType ? pageType + "Wrapper" : "dnaWrapper";

  const pageClass =
    pageType === "home" || pageType === "login" ? "coverPage" : "deniPage";

  return (
    <div id="deniApps" className={pageWrapperClass}>
      <Meta
        title={title}
        desc={desc}
        summary={summary}
        canonical={canonical}
        image={image}
        css={css}
        js={js}
      />
      <Header />

      <Container className={pageClass}>
        {authPage && !isReady && <Loader inline active></Loader>}
        {authPage && !user && isReady && <p>Please Login</p>}
        {(!authPage || !!user) && children}
      </Container>
      <Footer />
    </div>
  );
}
Example #5
Source File: AllSubscriptionsHOC.jsx    From HACC-Hui with MIT License 5 votes vote down vote up
/**
 * Higher order component that waits for the subscriptions.
 * @param WrappedComponent {React.Component} the wrapped component.
 * @return {React.Component} The WrappedComponent with subscriptions.
 * @memberOf ui/layouts
 */
function withAllSubscriptions(WrappedComponent) {
  const AllSubscriptionsHOC = (props) => ((props.loading) ? (
              <Loader active>Getting data.</Loader>
          ) :
          <WrappedComponent {...props} />
  );
  AllSubscriptionsHOC.propTypes = {
    loading: PropTypes.bool,
  };

  return withTracker(() => {
    const handles = [
      allSubs.subscribe(Administrators.getCollectionName()),
      allSubs.subscribe(Challenges.getCollectionName()),
      allSubs.subscribe(ChallengeInterests.getCollectionName()),
      allSubs.subscribe(ParticipantChallenges.getCollectionName()),
      allSubs.subscribe(ParticipantInterests.getCollectionName()),
      allSubs.subscribe(ParticipantSkills.getCollectionName()),
      allSubs.subscribe(Participants.getCollectionName()),
      allSubs.subscribe(ParticipantTools.getCollectionName()),
      allSubs.subscribe(Interests.getCollectionName()),
      allSubs.subscribe(Skills.getCollectionName()),
      allSubs.subscribe(Slugs.getCollectionName()),
      allSubs.subscribe(TeamChallenges.getCollectionName()),
      allSubs.subscribe(TeamParticipants.getCollectionName()),
      allSubs.subscribe(Teams.getCollectionName()),
      allSubs.subscribe(TeamSkills.getCollectionName()),
      allSubs.subscribe(TeamTools.getCollectionName()),
      allSubs.subscribe(Tools.getCollectionName()),
      allSubs.subscribe(TeamInvitations.getCollectionName()),
      allSubs.subscribe(Suggestions.getCollectionName()),
      allSubs.subscribe(WantsToJoin.getCollectionName()),
      allSubs.subscribe(CanCreateTeams.getCollectionName()),
      allSubs.subscribe(CanChangeChallenges.getCollectionName()),
      allSubs.subscribe(MinorParticipants.getCollectionName()),
    ];
    const loading = handles.some((handle) => !handle.ready());
    return {
      loading,
    };

  })(AllSubscriptionsHOC);
}
Example #6
Source File: NewUsersLIst.js    From social-network with MIT License 5 votes vote down vote up
render() {
    const { newUsers, username } = this.props;

    const users = newUsers.users.map((user) => {
      return (
        <List.Item key={user._id}>
          <Image
            avatar
            src={`/images/profile-picture/100x100/${user.profilePicture}`}
          />
          <List.Content>
            <List.Header
              as={Link}
              to={user.username === username ? "/profile" : "/" + user.username}
            >
              {user.username}
            </List.Header>

            <span style={{ color: "#757575" }}>
              joined {dayjs(user.date).fromNow()}
            </span>
          </List.Content>
        </List.Item>
      );
    });
    return (
      <Fragment>
        <List size="big">
          {newUsers.fetching ? (
            <Dimmer active>
              <Loader />
            </Dimmer>
          ) : null}
          {
            <List.Item>
              <List.Content>
                <List.Header> all users: {newUsers.usersCount}</List.Header>
              </List.Content>
            </List.Item>
          }
          {users}
          {newUsers.usersCount - newUsers.users.length !== 0 ? (
            <Button
              fluid
              loading={newUsers.fetchingNewUsers}
              onClick={() => this.fetchMoreUsers()}
            >
              More users
            </Button>
          ) : null}
        </List>
      </Fragment>
    );
  }
Example #7
Source File: MessengerContent.js    From social-network with MIT License 5 votes vote down vote up
render() {
    const { currentRoom, content, userId, profilePicture } = this.props;

    const loadedMessages = currentRoom.messages - content.messages.length;
    const messages = content.messages.map(message => (
      <MessengerMessages
        key={message._id || message.uuid}
        currentRoom={currentRoom}
        message={message}
        userId={userId}
        profilePicture={profilePicture}
      ></MessengerMessages>
    ));

    return (
      <div className="content">
        {content.initialMessagesFetchig ? (
          <Dimmer active>
            <Loader />
          </Dimmer>
        ) : null}
        <div className="contact-profile">
          <img
            src={`/images/profile-picture/100x100/${currentRoom.user.profilePicture}`}
            alt=""
          />
          <p>{currentRoom.user.firstName + " " + currentRoom.user.lastName}</p>
          <div className="social-media">
            <Popup
              content="Scroll to bottom."
              trigger={
                <i
                  onClick={this.handleScrollToBottom}
                  className="fa fa-arrow-down"
                  aria-hidden="true"
                ></i>
              }
            />

            <CallingModal></CallingModal>
            <Label basic color="red" pointing="left">
              This isn't working.
            </Label>
          </div>
        </div>
        <div
          className="messages"
          id="ContainerElementID"
          ref={this.messagesContainer}
        >
          {loadedMessages ? (
            <Button
              fluid
              disabled={content.messageFetching}
              loading={content.messageFetching}
              onClick={this.fetchMessages}
            >
              Load {currentRoom.messages - content.messages.length} more
            </Button>
          ) : null}

          <ul>
            {messages}
            {content.isTyping ? (
              <li className="sent" key={currentRoom.user._id}>
                <img
                  src={`/images/profile-picture/100x100/${currentRoom.user.profilePicture}`}
                  alt=""
                />
                <p>typing...</p>
              </li>
            ) : null}
          </ul>
        </div>
        <MessengerInput></MessengerInput>
      </div>
    );
  }
Example #8
Source File: index.js    From nextfeathers with Apache License 2.0 5 votes vote down vote up
export default function Posts(props) {
  const title = "Blog - Deni Apps";
  const desc =
    "Software Engineer for React.js, Node.js, GraphQL and JavaScript. Based in USA, Chinese/English speaking. Consulting/Freelancing for Web Development project: Code Audits/Reviews, Workshops, Training, Implementation ...";

  const summary = "DNA - DiNiApps";
  const canonical = "https://deniapps.com/blog";
  const image = "https://deniapps.com/images/dna.png";

  const seoData = {
    title,
    desc,
    summary,
    canonical,
    image,
  };

  const [isLoading, setIsLoading] = useState(false);
  const [isError, setIsError] = useState(false);
  const [list, setList] = useState(props.posts);

  const [pageId, setPageId] = useState(0);
  const [showLoadMore, setShowLoadMore] = useState(props.showLoadMore);

  const fetchList = async (pageId) => {
    setIsError(false);
    setIsLoading(true);
    try {
      const result = await getPublicPosts(pageId);
      //TO-DO: check status for error handling, and add pagination if needed.
      const newList = list.concat(result.data);
      if (result.total > newList.length) {
        setShowLoadMore(true);
      } else {
        setShowLoadMore(false);
      }
      setList(newList);
    } catch (err) {
      setIsError(true);
    }
    setIsLoading(false);
    return true;
  };

  const loadMore = async () => {
    const newPageId = pageId + 1;
    setPageId(newPageId);
    await fetchList(newPageId);
  };

  return (
    <Layout seoData={seoData}>
      <PostList
        posts={list}
        showLoadMore={showLoadMore}
        isLoading={isLoading}
        loadMore={loadMore}
      />
      {isError && <div>Something went wrong ...</div>}
      {isLoading && (
        <Segment textAlign="center">
          <Loader inline active>
            Loading...
          </Loader>
        </Segment>
      )}
    </Layout>
  );
}
Example #9
Source File: Write.js    From nextfeathers with Apache License 2.0 5 votes vote down vote up
// import { renewJWT } from "lib/authentication";

export default function Write() {
  const router = useRouter();
  const { id } = router.query;

  const [isLoading, setIsLoading] = useState(false);
  const [fatalError, setFatalError] = useState(null);
  const [data, setData] = useState({});

  const { signOut } = useContext(UserContext);

  const fetchData = async () => {
    if (!id) return false;
    if (id === "new") {
      setData({
        title: "Add New Post",
        data: {},
      });
      return true;
    }
    setFatalError(null);
    setIsLoading(true);
    try {
      let data = {};
      //check if draft exists, if so, restore it
      const draftResult = await getDraft(id);
      if (draftResult && draftResult.total > 0) {
        data = draftResult.data[0];
      } else {
        const result = await getPost(id);
        console.log("RESUTL", result);
        data = result;
      }

      setData({
        title: "Edit Post",
        data,
      });
    } catch (err) {
      setFatalError(err);
    }
    setIsLoading(false);
    return true;
  };

  useEffect(() => {
    fetchData();
  }, [id]);

  return (
    <div>
      {fatalError && <FatalError error={fatalError} />}
      {isLoading ? (
        <Segment textAlign="center">
          <Loader inline active>
            Loading...
          </Loader>
        </Segment>
      ) : (
        <>
          <Header
            as="h2"
            icon
            textAlign="center"
            style={{ marginBottom: "40px" }}
          >
            <Header.Content>{data.title}</Header.Content>
          </Header>
          <PostInput data={data.data} signOut={signOut} />
        </>
      )}
    </div>
  );
}
Example #10
Source File: PostPanel.js    From nextfeathers with Apache License 2.0 5 votes vote down vote up
PostPanel = (props) => {
  const posts = props.posts;
  if (!posts)
    return (
      <Segment textAlign="center">
        <Loader inline active>
          Loading...
        </Loader>
      </Segment>
    );
  const published = posts.filter((post) => !post.isDeleted && !post.isDraft);
  const drafts = posts.filter((post) => !post.isDeleted && post.isDraft);
  const deleted = posts.filter((post) => post.isDeleted);

  const publishedPanel = () => (
    <Tab.Pane attached={false}>
      <PostItemView items={published} onRemove={props.onRemove} />
    </Tab.Pane>
  );

  const draftsPanel = () => (
    <Tab.Pane attached={false}>
      <PostItemView items={drafts} onRemove={props.onRemove} />
    </Tab.Pane>
  );

  const deletedPanel = () => (
    <Tab.Pane attached={false}>
      <PostItemView
        items={deleted}
        onRemove={props.onPermanentlyRemove}
        onRecover={props.onRecover}
      />
    </Tab.Pane>
  );

  const panes = [
    {
      menuItem: "Published",
      displayName: "Published",
      render: publishedPanel,
    },
    {
      menuItem: "Drafts",
      displayName: "Drafts",
      render: draftsPanel,
    },
    {
      menuItem: "Deleted",
      displayName: "Deleted",
      render: deletedPanel,
    },
  ];

  return <Tab menu={{ secondary: true, pointing: true }} panes={panes} />;
}
Example #11
Source File: App.js    From substrate-evm with The Unlicense 5 votes vote down vote up
function Main () {
  const [accountAddress, setAccountAddress] = useState(null);
  const { apiState, keyring, keyringState } = useSubstrate();
  const accountPair =
    accountAddress &&
    keyringState === 'READY' &&
    keyring.getPair(accountAddress);

  const loader = text => (
    <Dimmer active>
      <Loader size='small'>{text}</Loader>
    </Dimmer>
  );

  if (apiState === 'ERROR') return loader('Error connecting to the blockchain');
  else if (apiState !== 'READY') return loader('Connecting to the blockchain');

  if (keyringState !== 'READY') {
    return loader(
      "Loading accounts (please review any extension's authorization)"
    );
  }

  const contextRef = createRef();

  return (
    <div ref={contextRef}>
      <Sticky context={contextRef}>
        <AccountSelector setAccountAddress={setAccountAddress} />
      </Sticky>
      <Container>
        <Grid stackable columns='equal'>
          <Grid.Row stretched>
            <NodeInfo />
            <Metadata />
            <BlockNumber />
            <BlockNumber finalized />
          </Grid.Row>
          <Grid.Row stretched>
            <EVMAccounts />
          </Grid.Row>
          <Grid.Row>
            <EVMContracts accountPair={accountPair} />
          </Grid.Row>
        </Grid>
        <DeveloperConsole />
      </Container>
    </div>
  );
}
Example #12
Source File: BestFitTeamDisplay.jsx    From HACC-Hui with MIT License 5 votes vote down vote up
render() {
    return (this.props.ready) ? this.renderPage() : <Loader active>Getting data</Loader>;
  }
Example #13
Source File: Dprofile.jsx    From HACC-Hui with MIT License 5 votes vote down vote up
/** Render the form. Use Uniforms: https://github.com/vazco/uniforms */
  render() {
    return (this.props.ready) ? this.renderPage() : <Loader active>Getting data</Loader>;
  }
Example #14
Source File: EditProfile.jsx    From HACC-Hui with MIT License 5 votes vote down vote up
/** If the subscription(s) have been received, render the page, otherwise show a loading icon. */
  render() {
    return (this.props.ready) ? this.renderPage() : <Loader active>Getting data</Loader>;
  }
Example #15
Source File: TeamCreation.jsx    From HACC-Hui with MIT License 5 votes vote down vote up
/** Render the form. Use Uniforms: https://github.com/vazco/uniforms */
  render() {
    // console.log(Teams.dumpAll());
    return (this.props.ready) ? this.renderPage() : <Loader active>Getting data</Loader>;
  }
Example #16
Source File: Home.js    From React-Ecommerce-Template with MIT License 5 votes vote down vote up
function Home() {
  const [product, setProduct] = useState([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    db.collection("Products").onSnapshot((snapshot) => {
      setProduct(snapshot.docs.map((doc) => doc.data()));
      setLoading(false);
    });
  }, [setProduct]);
  console.log(product);

  return (
    <div className="home">
      {loading ? (
        <Segment className="home__segment">
          <Dimmer active inverted>
            <Loader size="large" className="home__loaderMessage">
              Loading...
            </Loader>
          </Dimmer>
        </Segment>
      ) : (
        <Container>
          <Grid container columns={4} doubling stackable>
            {product.map((product, index) => {
              return (
                <Grid.Column stretched key={index}>
                  <Product
                    id={product.id}
                    key={product.id}
                    title={product.title}
                    price={product.price}
                    rating={product.rating}
                    imageUrl={product.imageUrl}
                  ></Product>
                </Grid.Column>
              );
            })}
          </Grid>
        </Container>
      )}
    </div>
  );
}
Example #17
Source File: us-timezone.js    From nextfeathers with Apache License 2.0 4 votes vote down vote up
USTimezone = () => {
  const [yourDT, setYourDT] = useState("");

  const [currentDT, setCurrentDT] = useState("");
  const [currentTZ, setCurrentTZ] = useState(getMyIANATZ());

  useEffect(
    () => {
      let getYourDTTimer = setInterval(() => {
        setYourDT(getDT(currentTZ));
      }, 1000);
      return () => {
        clearTimeout(getYourDTTimer);
      };
    },
    // useEffect will run only one time with empty []
    // if you pass a value to array,
    // like this - [data]
    // then clearTimeout will run every time
    // this value changes (useEffect re-run)
    []
  );

  useEffect(
    () => {
      let getDTTimer = setInterval(() => {
        setCurrentDT(getDT(currentTZ));
      }, 1000);
      return () => {
        clearInterval(getDTTimer);
      };
    },
    // useEffect will run only one time with empty []
    // if you pass a value to array,
    // like this - [data]
    // then clearTimeout will run every time
    // this value changes (useEffect re-run)
    [currentTZ]
  );

  const handleTZChange = (event, { value }) => {
    setCurrentDT("");
    setCurrentTZ(value);
  };

  const yourTZ = useMemo(() => getMyTZ(), []);

  const mainUSTZOpts = useMemo(() => mainUSTZ(), []);
  const groupTZValue = useMemo(() => getTZGroup(currentTZ), [currentTZ]);

  const allUSTZOpts = useMemo(() => allUSTZ(), []);

  return (
    <Layout seoData={seoData}>
      <h1>United States Timezones</h1>
      <Header as="h3" icon="time" content="Your Local Date Time" />
      <Segment inverted secondary>
        {yourDT || <Loader active inline />} {!!yourDT && ` - ${yourTZ}`}
      </Segment>
      <Header as="h3" icon="plane" content="Current Date Time in:" />
      <Dropdown
        search
        selection
        wrapSelection={false}
        options={mainUSTZOpts}
        value={groupTZValue}
        onChange={handleTZChange}
      />{" "}
      <Dropdown
        search
        selection
        wrapSelection={false}
        options={allUSTZOpts}
        value={currentTZ}
        onChange={handleTZChange}
      />
      <Segment raised>
        {currentDT || <Loader active inline size="small" />}
      </Segment>
    </Layout>
  );
}
Example #18
Source File: index.js    From nextfeathers with Apache License 2.0 4 votes vote down vote up
export default function Search(props) {
  const title = "Search Results - Deni Apps.com";
  const desc = `Search Results for  "${props.kw}"`;

  const summary = "Search - DiNiApps";
  const canonical = "https://deniapps.com/search/" + props.kw;
  const image = "https://deniapps.com/images/dna.png";

  const seoData = {
    title,
    desc,
    summary,
    canonical,
    image,
  };

  const isMount = useIsMount();

  const [isLoading, setIsLoading] = useState(false);
  const [isError, setIsError] = useState(false);
  const [list, setList] = useState(props.posts);

  const [pageId, setPageId] = useState(0);
  const [showLoadMore, setShowLoadMore] = useState(props.showLoadMore);

  const fetchList = async (pageId) => {
    setIsError(false);
    setIsLoading(true);
    try {
      const result = await searchPublicPosts(props.kw, pageId);
      //TO-DO: check status for error handling, and add pagination if needed.
      let newList = [];

      if (pageId > 0) {
        newList = list.concat(result.data);
      } else {
        newList = result.data;
      }

      if (result.total > newList.length) {
        setShowLoadMore(true);
      } else {
        setShowLoadMore(false);
      }
      setList(newList);
    } catch (err) {
      setIsError(true);
    }
    setIsLoading(false);
    return true;
  };

  useEffect(() => {
    console.log("kw", props.kw);
    if (!isMount) {
      setPageId(0);
      fetchList(0);
    }
  }, [props.kw]);

  const loadMore = async () => {
    const newPageId = pageId + 1;
    setPageId(newPageId);
    await fetchList(newPageId);
  };

  return (
    <Layout seoData={seoData}>
      <PostList
        posts={list}
        showLoadMore={showLoadMore}
        loadMore={loadMore}
        headline={desc}
      />
      {isError && <div>Something went wrong ...</div>}
      {isLoading && (
        <Segment textAlign="center">
          <Loader inline active>
            Loading...
          </Loader>
        </Segment>
      )}
    </Layout>
  );
}
Example #19
Source File: DefaultTextBlockEditor.jsx    From volto-slate with MIT License 4 votes vote down vote up
DefaultTextBlockEditor = (props) => {
  const {
    block,
    blocksConfig,
    data,
    detached = false,
    index,
    onChangeBlock,
    onInsertBlock,
    onMutateBlock,
    onSelectBlock,
    pathname,
    properties,
    selected,
    uploadRequest,
    uploadContent,
    uploadedContent,
    defaultSelection,
    saveSlateBlockSelection,
    allowedBlocks,
    formTitle,
    formDescription,
  } = props;

  const { slate } = config.settings;
  const { textblockExtensions } = slate;
  const { value } = data;

  // const [addNewBlockOpened, setAddNewBlockOpened] = React.useState();
  const [showDropzone, setShowDropzone] = React.useState(false);
  const [uploading, setUploading] = React.useState(false);
  const [newImageId, setNewImageId] = React.useState(null);

  const prevReq = React.useRef(null);

  const withBlockProperties = React.useCallback(
    (editor) => {
      editor.getBlockProps = () => props;
      return editor;
    },
    [props],
  );

  const slateSettings = React.useMemo(
    () => ({
      ...config.settings.slate,
      persistentHelpers: [
        ...config.settings.slate.persistentHelpers,
        PersistentSlashMenu,
      ],
    }),
    [],
  );

  const onDrop = React.useCallback(
    (files) => {
      // TODO: need to fix setUploading, treat uploading indicator
      // inteligently, show progress report on uploading files
      setUploading(true);
      files.forEach((file) => {
        const [mime] = file.type.split('/');
        if (mime !== 'image') return;

        readAsDataURL(file).then((data) => {
          const fields = data.match(/^data:(.*);(.*),(.*)$/);
          uploadContent(
            getBaseUrl(pathname),
            {
              '@type': 'Image',
              title: file.name,
              image: {
                data: fields[3],
                encoding: fields[2],
                'content-type': fields[1],
                filename: file.name,
              },
            },
            block,
          );
        });
      });
      setShowDropzone(false);
    },
    [pathname, uploadContent, block],
  );

  const { loaded, loading } = uploadRequest;
  const imageId = uploadedContent['@id'];
  const prevLoaded = prevReq.current;

  React.useEffect(() => {
    if (loaded && !loading && !prevLoaded && newImageId !== imageId) {
      const url = flattenToAppURL(imageId);
      setNewImageId(imageId);

      createImageBlock(url, index, props);
    }
    prevReq.current = loaded;
  }, [props, loaded, loading, prevLoaded, imageId, newImageId, index]);

  const handleUpdate = React.useCallback(
    (editor) => {
      // defaultSelection is used for things such as "restoring" the selection
      // when joining blocks or moving the selection to block start on block
      // split
      if (defaultSelection) {
        const selection = parseDefaultSelection(editor, defaultSelection);
        if (selection) {
          setTimeout(() => {
            Transforms.select(editor, selection);
            saveSlateBlockSelection(block, null);
          }, 120);
          // TODO: use React sync render API
          // without setTimeout, the join is not correct. Slate uses internally
          // a 100ms throttle, so setting to a bigger value seems to help
        }
      }
    },
    [defaultSelection, block, saveSlateBlockSelection],
  );

  const onEditorChange = (value, editor) => {
    ReactDOM.unstable_batchedUpdates(() => {
      onChangeBlock(block, {
        ...data,
        value,
        plaintext: serializeNodesToText(value || []),
        // TODO: also add html serialized value
      });
      deconstructToVoltoBlocks(editor);
    });
  };

  // Get editing instructions from block settings or props
  let instructions = data?.instructions?.data || data?.instructions;
  if (!instructions || instructions === '<p><br/></p>') {
    instructions = formDescription;
  }

  const intl = useIntl();
  const placeholder =
    data.placeholder || formTitle || intl.formatMessage(messages.text);
  const schema = TextBlockSchema(data);

  const disableNewBlocks = data?.disableNewBlocks || detached;
  const { ref, inView } = useInView({
    threshold: 0,
    rootMargin: '0px 0px 200px 0px',
  });

  const handleFocus = React.useCallback(() => {
    if (!selected) {
      onSelectBlock(block);
    }
  }, [onSelectBlock, selected, block]);

  return (
    <div className="text-slate-editor-inner" ref={ref}>
      <>
        <Dropzone
          disableClick
          onDrop={onDrop}
          className="dropzone"
          onDragOver={() => setShowDropzone(true)}
          onDragLeave={() => setShowDropzone(false)}
        >
          {({ getRootProps, getInputProps }) => {
            return showDropzone ? (
              <div className="drop-indicator">
                {uploading ? (
                  <Dimmer active>
                    <Loader indeterminate>Uploading image</Loader>
                  </Dimmer>
                ) : (
                  <Message>
                    <center>
                      <img src={imageBlockSVG} alt="" />
                    </center>
                  </Message>
                )}
              </div>
            ) : (
              <>
                <SlateEditor
                  index={index}
                  readOnly={!inView}
                  properties={properties}
                  extensions={textblockExtensions}
                  renderExtensions={[withBlockProperties]}
                  value={value}
                  block={block /* is this needed? */}
                  defaultSelection={defaultSelection}
                  onUpdate={handleUpdate}
                  debug={DEBUG}
                  onFocus={handleFocus}
                  onChange={(value, editor) => onEditorChange(value, editor)}
                  onKeyDown={handleKey}
                  selected={selected}
                  placeholder={placeholder}
                  slateSettings={slateSettings}
                />
                {DEBUG ? <div>{block}</div> : ''}
              </>
            );
          }}
        </Dropzone>

        {selected && !data.plaintext?.trim() && !disableNewBlocks && (
          <BlockChooserButton
            data={data}
            block={block}
            onInsertBlock={(id, value) => {
              onSelectBlock(onInsertBlock(id, value));
            }}
            onMutateBlock={onMutateBlock}
            allowedBlocks={allowedBlocks}
            blocksConfig={blocksConfig}
            size="24px"
            className="block-add-button"
            properties={properties}
          />
        )}

        <SidebarPortal selected={selected}>
          <div id="slate-plugin-sidebar"></div>
          {instructions ? (
            <Segment attached>
              <div dangerouslySetInnerHTML={{ __html: instructions }} />
            </Segment>
          ) : (
            <>
              <ShortcutListing />
              <MarkdownIntroduction />
              <BlockDataForm
                schema={schema}
                title={schema.title}
                onChangeField={(id, value) => {
                  onChangeBlock(block, {
                    ...data,
                    [id]: value,
                  });
                }}
                formData={data}
                block={block}
              />
            </>
          )}
        </SidebarPortal>
      </>
    </div>
  );
}
Example #20
Source File: photo-collage-gallery.js    From nextfeathers with Apache License 2.0 4 votes vote down vote up
UnsplashPhotos = () => {
  let [photos, setPhotos] = useState(null);
  let [query, setQuery] = useState("");
  let [isBottom, setIsBottom] = useState(false);
  let [page, setPage] = useState(1);
  let [active, setActive] = useState(false);
  let [currentIndex, setCurrentIndex] = useState(0);

  const queryInputRef = useRef(null);
  const photoListRef = useRef(null);

  const numberOfPhotos = 30;
  // for demo purpose, only show up to 5 pages
  const maxPages = 5;

  function handleScroll() {
    const scrollTop =
      (document.documentElement && document.documentElement.scrollTop) ||
      document.body.scrollTop;
    const scrollHeight =
      (document.documentElement && document.documentElement.scrollHeight) ||
      document.body.scrollHeight;
    if (scrollTop + window.innerHeight + 50 >= scrollHeight) {
      setIsBottom(true);
    }
  }

  // add listener to scroll even
  // setIsBottom when reach the bottom

  // option 1:   list has fixed height
  // useEffect(() => {
  //   // use search
  //   const list = photoListRef.current;
  //   console.log(list);

  //   list.addEventListener("scroll", (e) => {
  //     const el = e.target;
  //     if (el.scrollTop + el.clientHeight + 50 === el.scrollHeight) {
  //       setIsBottom(true);
  //     }
  //   });
  //   return () => list.removeEventListener("scroll");
  // }, []);

  // option 2: list does not have fixed height, then use window

  useEffect(() => {
    window.addEventListener("scroll", handleScroll);
    return () => window.removeEventListener("scroll", handleScroll);
  }, []);

  useEffect(async () => {
    queryInputRef.current.focus();
    // use random for initial page load
    const randomUrl =
      "https://api.unsplash.com/photos/random/?count=" +
      numberOfPhotos +
      "&client_id=" +
      clientID;

    const url =
      "https://api.unsplash.com/search/photos/?per_page=" +
      numberOfPhotos +
      "&page=" +
      page +
      "&client_id=" +
      clientID;

    const photosUrl = query ? `${url}&query=${query}` : randomUrl;

    // only fetch one for ramdomulr
    // when there is query, it's using search API
    if (page === 1 || (query && isBottom && page <= maxPages)) {
      try {
        const data = await getPhotos(photosUrl);
        console.log(data);
        // random photo api returns array, but search api returns object
        const photoFetched = Array.isArray(data) ? data : data.results;
        if (photos === null) {
          photos = photoFetched;
        } else {
          photos = photos.concat(photoFetched);
        }

        setPhotos(photos);
        // if photo found, increase page
        if (photoFetched.length > 0) {
          setPage(page + 1);
          setIsBottom(false);
        }
      } catch (error) {
        setPhotos([]);
        console.log(error);
      }
    }
  }, [query, isBottom]);

  const searchPhotos = (e) => {
    // console.log(queryInputRef.current.value);
    e.preventDefault();
    setPhotos(null); //show loading
    setPage(1);
    setQuery(queryInputRef.current.value);
  };

  return (
    <div className="dnx-box">
      {/* <form onSubmit={searchPhotos}>
        <Input
          size="large"
          icon="search"
          id="dnx-unsplash-search-input"
          ref={queryInputRef}
          onChange={(e) => setQuery(e.target.value)}
          placeholder="Search Photos on Unsplash"
          fluid
        />
      </form> */}
      <Form
        id="unsplash-search"
        className="unsplash-search"
        onSubmit={searchPhotos}
      >
        <input
          id="dnx-unsplash-search-input"
          ref={queryInputRef}
          placeholder="Search Photos on Unsplash"
          type="search"
        />
      </Form>

      <Warnings />
      {photos === null && <Loader active inline="centered" />}
      {photos !== null && photos.length === 0 && <p>No results</p>}

      <ul className="dnx-photo-grid" ref={photoListRef}>
        {photos !== null &&
          photos.length > 0 &&
          photos.map((photo, idx) => {
            return (
              <li key={photo.id}>
                <img
                  src={photo.urls.regular}
                  onClick={() => {
                    setCurrentIndex(idx);
                    setActive(true);
                  }}
                />
              </li>
            );
          })}
      </ul>

      {photos !== null && photos.length > 0 && (
        <Gallery
          active={active}
          currentIndex={currentIndex}
          setCurrentIndex={setCurrentIndex}
          onClickOutside={() => setActive(false)}
          onClose={() => setActive(false)}
          keyboardNavigation={true}
          images={photos}
        />
      )}
    </div>
  );
}
Example #21
Source File: ChatProfile.js    From react-chat-app with MIT License 4 votes vote down vote up
ChatProfile = (props) => {
  const { userObject, convertedName } = useAuth();
  const [avatarURL, setAvatarURL] = useState();
  const [userStatus, setUserStatus] = useState();
  const inputRef = useRef(null);
  const [image, setImage] = useState();
  const [avatarState, setAvatarState] = useState(false);
  const [statusState, setStatusState] = useState(false);
  const [avatarVisibility, setAvatarVisibility] = useState(true);
  const { conn } = useContext(ChatEngineContext)

  const capitalize = (str, lower = true) => {
    return (lower ? str.toLowerCase() : str).replace(
      /(?:^|\s|["'([{])+\S/g,
      (match) => match.toUpperCase()
    );
  };

  const onFileAttach = (file) => {
    setImage(file);
  };

  const updateAv = () => {
    const myHeaders = new Headers();
    myHeaders.append("Project-ID", process.env.REACT_APP_PROJECT_ID);
    myHeaders.append("User-Name", convertedName);
    myHeaders.append("User-Secret", userObject.uid);

    const formdata = new FormData();
    formdata.append("avatar", image, image.name);

    const requestOptions = {
      method: "PATCH",
      headers: myHeaders,
      body: formdata,
      redirect: "follow",
    };

    fetch("https://api.chatengine.io/users/me/", requestOptions)
      .then(() => {
        setAvatarState(false)
        setAvatarURL()
      }
      )
  };

  useEffect(() => {
    var myHeaders = new Headers();
    myHeaders.append("Project-ID", process.env.REACT_APP_PROJECT_ID);
    myHeaders.append("User-Name", props.conn.userName);
    myHeaders.append("User-Secret", props.conn.userSecret);

    var requestOptions = {
      method: "GET",
      headers: myHeaders,
      redirect: "follow",
    };

    fetch("https://api.chatengine.io/users/me/", requestOptions)
      .then((response) => response.json())
      .then((result) => {
        setUserStatus(result.first_name)
        setAvatarURL(result.avatar);
        setAvatarState(true);
        setStatusState(true)

      });
  }, [avatarState]);

  return (
    <div className="chat-profile-container">
      <input
        type="file"
        ref={inputRef}
        className="image-input"
        accept="image/jpeg,image/png"
        onChange={(e) => {
          const file = e.target?.files?.[0];
          if (file) {
            onFileAttach(file);
            setAvatarVisibility(false);
          }
        }}
      />

      {!!image && (
        <ChatAvatar
          crop
          file={image}
          header="Set Your Avatar"
          mode="message"
          username={props.conn.userName}
          userstatus={userStatus}
          onSubmit={(croppedImage) => {
            setImage(croppedImage);
            updateAv();
            setImage(null);
            setAvatarVisibility(true);
          }}
          close={() => {
            setImage(null)
            setAvatarVisibility(true);
          }}
        />
      )}

      {userObject.uid && avatarVisibility ? (
        <div className="current-user-info">
          <IconGroup
            onClick={() => {
              if (conn.userName === "john%20doe") {
                  alert("Changing avatar is disabled on sample account, sorry!")
                return null
                }
              const input = inputRef.current;
              if (input) {
                input.value = "";
                input.click();
              }
            }}
            className="user-avatar"
            size="large"
          >
            {avatarState ? (
              <>
                {avatarURL ? (
                  <img
                    src={avatarURL}
                    style={{ borderRadius: "50%", width: "120px" }}
                    alt=""
                  />
                ) : (
                  <img
                    src={empty}
                    style={{ borderRadius: "50%", width: "120px" }}
                    alt=""
                  />
                )}
              </>
            ) : (
              <img src={loadingAnimation} alt="" />
            )}

            <Icon corner name="camera" inverted circular />
          </IconGroup>


        </div>
      ) : (
        <div className="user-loading">
          <Loader active size="small" />
        </div>
      )}

      {!image ?
        <div className="chat-profile-info">
          <div className="current-username">
            <div className="username-border">
              {capitalize(decodeURIComponent(convertedName))}
            </div>

          </div>

          {statusState ?
            <UserStatus userStatus={userStatus} /> : ""}

        </div>
        : ""}

    </div>
  );
}
Example #22
Source File: ProfilePage.js    From social-network with MIT License 4 votes vote down vote up
render() {
    const { user, alert } = this.props;
    const hasMore =
      user.data.postsCount === user.data.posts.length ? false : true;
    const posts = user.data.posts.map(post => {
      return (
        <Modal
          key={post._id}
          size="small"
          trigger={
            <div className="gallery-item">
              <img
                src={`/images/post-images/thumbnail/${post.photo}`}
                className="gallery-image"
                alt=""
              />

              <div className="gallery-item-info">
                <ul>
                  <li className="gallery-item-likes">
                    <span className="visually-hidden">Likes:</span>
                    <Icon name="heart" /> {post.likes}
                  </li>
                  <li className="gallery-item-comments">
                    <span className="visually-hidden">Comments:</span>
                    <Icon name="comment" /> {post.comments}
                  </li>
                </ul>
              </div>
            </div>
          }
        >
          <Post
            post={{
              ...post,
              author: [
                {
                  profilePicture: user.data.profilePicture,
                  username: user.data.username,
                  _id: user.data._id
                }
              ]
            }}
          />
        </Modal>
      );
    });

    const followingList = user.data.follwingUsers.length
      ? user.data.follwingUsers.map(({ user }) => (
          <FollowingFollowerList
            key={user._id}
            user={user}
          ></FollowingFollowerList>
        ))
      : "No followings";

    const followerList = user.data.followerUsers.length
      ? user.data.followerUsers.map(({ user }) => (
          <FollowingFollowerList
            key={user._id}
            user={user}
          ></FollowingFollowerList>
        ))
      : "No followers";

    return (
      <div className="main">
        {user.loadingUser ? (
          <Dimmer active>
            <Loader />
          </Dimmer>
        ) : (
          <Fragment>
            {user.deleting ? (
              <Dimmer active>
                <Loader />
              </Dimmer>
            ) : null}

            <header>
              <div className="container">
                {alert.type ? <Messages alert={alert} /> : null}
                <div className="profile">
                  <div className="profile-image">
                    <img
                      src={`/images/profile-picture/100x100/${user.data.profilePicture}`}
                      alt=""
                    />
                  </div>

                  <div className="profile-user-settings">
                    <h1 className="profile-user-name">{user.data.username}</h1>

                    <Button
                      as={Link}
                      to="/posts/upload"
                      className="profile-edit-btn"
                      size="large"
                      icon
                      labelPosition="right"
                    >
                      Add post
                      <Icon name="upload" />
                    </Button>
                    <EditProfileModal>
                      <Button
                        className="profile-edit-btn"
                        size="large"
                        icon
                        labelPosition="right"
                      >
                        Profile settings
                        <Icon name="setting" />
                      </Button>
                    </EditProfileModal>
                  </div>
                  <div className="profile-stats">
                    <ul>
                      <li>
                        <span className="profile-stat-count">
                          {user.data.postsCount}
                        </span>{" "}
                        posts
                      </li>
                      <Modal
                        trigger={
                          <li onClick={this.getFollowers}>
                            <span className="profile-stat-count">
                              {user.data.followers}
                            </span>{" "}
                            followers
                          </li>
                        }
                      >
                        <Modal.Header>Followers</Modal.Header>
                        <Modal.Content scrolling>
                          <Modal.Description>
                            <List verticalAlign="middle" size="huge">
                              {followerList}
                            </List>
                          </Modal.Description>
                        </Modal.Content>
                      </Modal>
                      <Modal
                        trigger={
                          <li onClick={this.getFollowings}>
                            <span className="profile-stat-count">
                              {user.data.followings}
                            </span>{" "}
                            following
                          </li>
                        }
                      >
                        <Modal.Header>Following</Modal.Header>
                        <Modal.Content scrolling>
                          <Modal.Description>
                            <List verticalAlign="middle" size="huge">
                              {followingList}
                            </List>
                          </Modal.Description>
                        </Modal.Content>
                      </Modal>
                    </ul>
                  </div>
                  <div className="profile-bio">
                    <div className="profile-real-name">
                      {user.data.firstName + " " + user.data.lastName}
                    </div>
                    <div className="profile-bio-description">
                      <Linkify options={linkifyOptions}>
                        {user.data.bio}
                      </Linkify>
                    </div>
                  </div>
                </div>
              </div>
            </header>
            <main>
              <div className="container">
                {user.data.postsCount === 0 ? (
                  <Message info size="large">
                    You have no posts. Share your first picture:{" "}
                    <Button
                      as={Link}
                      to="/posts/upload"
                      className="profile-edit-btn"
                      size="large"
                      icon
                      labelPosition="right"
                    >
                      Add post
                      <Icon name="upload" />
                    </Button>
                  </Message>
                ) : (
                  <InfiniteScroll
                    className="gallery"
                    dataLength={user.data.posts.length} //This is important field to render the next data
                    next={this.fetchData}
                    hasMore={hasMore}
                    loader={<h4>Loading...</h4>}
                  >
                    {posts}
                  </InfiniteScroll>
                )}
              </div>
            </main>
            <Divider hidden></Divider>
          </Fragment>
        )}
      </div>
    );
  }
Example #23
Source File: UserProfile.js    From social-network with MIT License 4 votes vote down vote up
render() {
    const { userProfileData, fetchingUserData, alert } = this.props;
    const hasMore =
      userProfileData.data.postsCount === userProfileData.data.posts.length
        ? false
        : true;
    if (alert.type) {
      return (
        <div className="container">
          <Messages alert={alert} />
        </div>
      );
    }
    if (userProfileData.loadingUser || fetchingUserData) {
      return (
        <Dimmer active>
          <Loader />
        </Dimmer>
      );
    } else {
      const posts = userProfileData.data.posts.map(post => {
        return (
          <Modal
            key={post._id}
            size="small"
            trigger={
              <div className="gallery-item">
                <img
                  src={`/images/post-images/thumbnail/${post.photo}`}
                  className="gallery-image"
                  alt=""
                />

                <div className="gallery-item-info">
                  <ul>
                    <li className="gallery-item-likes">
                      <span className="visually-hidden">Likes:</span>
                      <Icon name="heart" /> {post.likes}
                    </li>
                    <li className="gallery-item-comments">
                      <span className="visually-hidden">Comments:</span>
                      <Icon name="comment" /> {post.comments}
                    </li>
                  </ul>
                </div>
              </div>
            }
          >
            <Post
              post={{
                ...post,
                author: [
                  {
                    profilePicture: userProfileData.data.profilePicture,
                    username: userProfileData.data.username,
                    _id: userProfileData.data._id
                  }
                ]
              }}
            />
          </Modal>
        );
      });

      const followingList = userProfileData.data.follwingUsers.length
        ? userProfileData.data.follwingUsers.map(({ user }) => (
            <FollowingFollowerList
              key={user._id}
              user={user}
            ></FollowingFollowerList>
          ))
        : "No followings";

      const followerList = userProfileData.data.followerUsers.length
        ? userProfileData.data.followerUsers.map(({ user }) => (
            <FollowingFollowerList
              key={user._id}
              user={user}
            ></FollowingFollowerList>
          ))
        : "No followers";

      return (
        <Fragment>
          <header>
            <div className="container">
              <div className="profile">
                <div className="profile-image">
                  <img
                    src={`/images/profile-picture/100x100/${userProfileData.data.profilePicture}`}
                    alt=""
                  />
                </div>

                <div className="profile-user-settings">
                  <h1 className="profile-user-name">
                    {userProfileData.data.username}
                  </h1>

                  <FollowButton
                    userId={userProfileData.data._id}
                  ></FollowButton>
                </div>

                <div className="profile-stats">
                  <ul>
                    <li>
                      <span className="profile-stat-count">
                        {userProfileData.data.postsCount}
                      </span>{" "}
                      posts
                    </li>
                    <Modal
                      trigger={
                        <li onClick={this.getFollowers}>
                          <span className="profile-stat-count">
                            {userProfileData.data.followers}
                          </span>{" "}
                          followers
                        </li>
                      }
                    >
                      <Modal.Header>Followers</Modal.Header>
                      <Modal.Content scrolling>
                        <Modal.Description>
                          <List selection verticalAlign="middle" size="huge">
                            {followerList}
                          </List>
                        </Modal.Description>
                      </Modal.Content>
                    </Modal>
                    <Modal
                      trigger={
                        <li onClick={this.getFollowings}>
                          <span className="profile-stat-count">
                            {userProfileData.data.followings}
                          </span>{" "}
                          following
                        </li>
                      }
                    >
                      <Modal.Header>Following</Modal.Header>
                      <Modal.Content scrolling>
                        <Modal.Description>
                          <List selection verticalAlign="middle" size="huge">
                            {followingList}
                          </List>
                        </Modal.Description>
                      </Modal.Content>
                    </Modal>
                  </ul>
                </div>

                <div className="profile-bio">
                  <div className="profile-real-name">
                    {userProfileData.data.firstName +
                      " " +
                      userProfileData.data.lastName}
                  </div>
                  <div className="profile-bio-description">
                    <Linkify options={linkifyOptions}>
                      {userProfileData.data.bio}
                    </Linkify>
                  </div>
                </div>
              </div>
            </div>
          </header>
          <main>
            <div className="container">
              {userProfileData.data.postsCount === 0 ? (
                <Message info size="large">
                  This user has no posts yet.
                </Message>
              ) : (
                <InfiniteScroll
                  className="gallery"
                  dataLength={userProfileData.data.posts.length} //This is important field to render the next data
                  next={this.fetchData}
                  hasMore={hasMore}
                  loader={<h4>Loading...</h4>}
                >
                  {posts}
                </InfiniteScroll>
              )}
            </div>
          </main>
          <Divider hidden></Divider>
        </Fragment>
      );
    }
  }
Example #24
Source File: index.js    From cicero-word-add-in with Apache License 2.0 4 votes vote down vote up
LibraryComponent = () => {
  const [templates, setTemplates] = useState(null);
  const [overallCounter, setOverallCounter] = useState({});

  useEffect(() => {
    /**
     * Loads the template library from https://templates.accordproject.org/ and stores them in the state.
     */
    async function load() {
      const templateLibrary = new TemplateLibrary();
      const templateIndex = await templateLibrary
        .getTemplateIndex({
          latestVersion: true,
        });
      setTemplates(templateIndex);
    }
    load();
  }, []);

  /**
   * Renders an uploaded template.
   *
   * @param {MouseEvent} event event containing the file object
   */
  const onUploadTemplate = async event => {
    const fileUploaded = event.target.files[0];
    try {
      const template = await Template.fromArchive(fileUploaded);
      const ciceroMark = templateToCiceroMark(template);
      setup(ciceroMark, template);
    }
    catch (error) {
      Office.context.ui.displayDialogAsync(`${window.location.origin}/bad-file.html`, { width: 30, height: 8 });
    }
  };

  useEffect(() => {
    /**
     * Initializes the document by fetching the templates whose identifier is stored in CustomXMLPart.
     */
    async function initializeDocument() {
      Office.context.document.customXmlParts.getByNamespaceAsync(CUSTOM_XML_NAMESPACE, result => {
        if (result.status === Office.AsyncResultStatus.Succeeded) {
          if (result.value.length > 0) {
            const customXmlPart = result.value[0];
            customXmlPart.getNodesAsync('*/*', async result => {
              if (result.status === Office.AsyncResultStatus.Succeeded) {
                for (let index=0; index<result.value.length; ++index) {
                  const templateIdentifier = result.value[index].namespaceUri;
                  const templateIndex = templates[templateIdentifier];
                  const template = await Template.fromUrl(templateIndex.ciceroUrl);
                  const ciceroMark = templateToCiceroMark(template);
                  const numeration = VariableVisitor.getVariables(ciceroMark);
                  Word.run(async context => {
                    const contentControls = context.document.body.contentControls;
                    contentControls.load(['items/length', 'title']);
                    await context.sync();
                    for (let index=0; index<contentControls.items.length; ++index) {
                      if (numeration.includes(contentControls.items[index].title)) {
                        attachVariableChangeListener(contentControls.items[index].title);
                      }
                    }
                    triggerClauseParse(templateIdentifier, template);
                  });
                }
              }
            });
          }
        }
      });
    }
    if (templates !== null) {
      initializeDocument();
    }
  }, [templates]);


  /**
   * Sets up a template for rendering.
   *
   * @param {object} ciceroMark Ciceromark JSON
   * @param {object} template   Template object
   */
  const setup = async (ciceroMark, template) => {
    await Word.run(async context => {
      let counter = { ...overallCounter };
      let ooxml = ooxmlGenerator(ciceroMark, counter, '');
      const templateIdentifier = template.getIdentifier();
      ooxml = `
        <w:sdt>
          <w:sdtPr>
            <w:lock w:val="contentLocked" />
            <w:alias w:val="${templateIdentifier}"/>
          </w:sdtPr>
          <w:sdtContent>
          ${ooxml}
          </w:sdtContent>
        </w:sdt>
      `;
      ooxml = `<pkg:package xmlns:pkg="http://schemas.microsoft.com/office/2006/xmlPackage">
      <pkg:part pkg:name="/_rels/.rels" pkg:contentType="application/vnd.openxmlformats-package.relationships+xml">
        <pkg:xmlData>
          <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
            <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="word/document.xml"/>
          </Relationships>
        </pkg:xmlData>
      </pkg:part>
      <pkg:part pkg:name="/word/document.xml" pkg:contentType="application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml">
        <pkg:xmlData>
          <w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" >
          ${ooxml}
          <w:p />
          </w:document>
        </pkg:xmlData>
      </pkg:part>
      ${spec}
      </pkg:package>`;
      context.document.body.insertOoxml(ooxml, Word.InsertLocation.end);
      await context.sync();
      setOverallCounter({
        ...overallCounter,
        ...counter,
      });
      for (const variableText in counter) {
        for (let index=1; index<=counter[variableText].count; ++index) {
          attachVariableChangeListener(
            titleGenerator(`${variableText.toUpperCase()[0]}${variableText.substring(1)}${index}`, counter[variableText].type)
          );
        }
      }
      triggerClauseParse(templateIdentifier, template);
    });
  };

  /**
   * Converts a template text to CiceroMark JSON.
   *
   * @param {object} template The template object
   * @returns {object} CiceroMark JSON of a template
   */
  const templateToCiceroMark = template => {
    const sampleText = template.getMetadata().getSample();
    const clause = new Clause(template);
    clause.parse(sampleText);
    const ciceroMark = clause.draft({ format : 'ciceromark_parsed' });
    return ciceroMark;
  };

  /**
   * Fetches templateIndex from https://templates.accordproject.org/, load the template, and save template details to CustomXML.
   *
   * @param {object} templateIndex Details of a particular template like URL, author, displayName, etc.
   */
  const loadTemplateText = async templateIndex => {
    // URL to compiled archive
    const template = await Template.fromUrl(templateIndex.ciceroUrl);
    const ciceroMark = templateToCiceroMark(template);
    const templateIdentifier = template.getIdentifier();
    saveTemplateToXml(ciceroMark, template, templateIdentifier);
  };

  /**
   * Sets up the template for rendering and saves it to the XML if the identifier of template is unique.
   *
   * @param {object} ciceroMark         CiceroMark JSON of a template
   * @param {object} template           Template object
   * @param {string} templateIdentifier Identifier for a template
   */
  const saveTemplateToXml = (ciceroMark, template, templateIdentifier) => {
    Office.context.document.customXmlParts.getByNamespaceAsync(CUSTOM_XML_NAMESPACE, result => {
      if (result.status === Office.AsyncResultStatus.Succeeded) {
        if (result.value.length === 0) {
          setup(ciceroMark, template);
          const xml = XML_HEADER +
          `<templates xmlns="${CUSTOM_XML_NAMESPACE}">` +
            `<template xmlns="${templateIdentifier}" />` +
          '</templates>';
          Office.context.document.customXmlParts.addAsync(xml);
        }
        else {
          const customXmlPart = result.value[0];
          customXmlPart.getNodesAsync('*/*', result => {
            if (result.status === Office.AsyncResultStatus.Succeeded) {
              let identifierExists = false;
              let newXml = XML_HEADER + `<templates xmlns="${CUSTOM_XML_NAMESPACE}">`;
              if (result.value.length > 0) {
                for (let node=0; node < result.value.length; ++node) {
                  if (result.value[node].namespaceUri !== templateIdentifier) {
                    newXml += `<template xmlns="${result.value[node].namespaceUri}" />`;
                  }
                  else {
                    identifierExists = true;
                  }
                }
              }
              if(!identifierExists){
                setup(ciceroMark, template);
                newXml += `<template xmlns="${templateIdentifier}" />`;
                newXml += '</templates>';
                Office.context.document.customXmlParts.getByNamespaceAsync(CUSTOM_XML_NAMESPACE, res => {
                  if (res.status === Office.AsyncResultStatus.Succeeded) {
                    for (let index=0; index<res.value.length; ++index) {
                      res.value[index].deleteAsync();
                    }
                  }
                });
                Office.context.document.customXmlParts.addAsync(newXml);
              }else{
                toast(
                  {
                    title: 'Duplicate template',
                    description: <p>Template cannot be inserted as it is already present in the document.</p>,
                    type: 'error',
                    time: 5000,
                    animation: 'fly down',
                  },
                );
              }
            }
          });
        }
      }
    });
  };

  /**
   * Redirects to the template URL.
   *
   * @param {object} template Template object
   */
  const goToTemplateDetail = template => {
    const templateOrigin = new URL(template.url).origin;
    const { name, version } = template;
    window.open(`${templateOrigin}/${name}@${version}.html`, '_blank');
  };

  if (!templates) {
    return <Loader active>Loading</Loader>;
  }

  return (
    <TemplateLibraryRenderer
      items = {Object.values(templates)}
      onPrimaryButtonClick={loadTemplateText}
      onSecondaryButtonClick={goToTemplateDetail}
      onUploadItem={onUploadTemplate}
    />
  );
}
Example #25
Source File: PostList.js    From nextfeathers with Apache License 2.0 4 votes vote down vote up
//List => Panel => ItemView

export default function PostList() {
  const [isLoading, setIsLoading] = useState(false);
  const [fatalError, setFatalError] = useState(false);
  const [list, setList] = useState([]);
  const [pageId, setPageId] = useState(0);
  const [showMore, setShowMore] = useState(false);

  const router = useRouter();
  const [message, setMessage] = useState(router.query.message);

  const fetchList = async (pageId) => {
    setFatalError(null);
    setIsLoading(true);
    try {
      const result = await getPosts(pageId);
      //TO-DO: check status for error handling, and add pagination if needed.
      const newList = list.concat(result.data);
      if (result.total > newList.length) {
        setShowMore(true);
      } else {
        setShowMore(false);
      }
      setList(newList);
    } catch (err) {
      // console.log(err.response.status);
      // if (err.response && err.response.status === 401) {
      // }
      setFatalError(err);
    }
    setIsLoading(false);
    return true;
  };

  useEffect(() => {
    fetchList(pageId);
    let msgTimer = setTimeout(() => {
      setMessage("");
    }, 3000);
    return () => {
      clearTimeout(msgTimer);
    };
  }, [pageId]);

  const loadMore = (e) => {
    console.log(e);
    e.preventDefault();
    setPageId(pageId + 1);
  };

  const handleRemove = async (id) => {
    await deletePost(id);
    // await fetchList();
    const newList = list.map((item) => {
      if (item._id === id) {
        item.isDeleted = true;
      }
      return item;
    });
    setList(newList);
  };

  const handleRecover = async (id) => {
    await undeletePost(id);
    // await fetchList();
    const newList = list.map((item) => {
      if (item._id === id) {
        item.isDeleted = false;
      }
      return item;
    });
    setList(newList);
  };

  const handlePermanentlyRemove = async (id) => {
    await permanentlyDeletePost(id);
    // await fetchList();
    const newList = list.filter((item) => item._id != id);
    setList(newList);
  };

  return (
    <div>
      {fatalError && <FatalError error={fatalError} />}
      {!fatalError && (
        <>
          <Header
            as="h2"
            icon
            textAlign="center"
            style={{ marginBottom: "40px" }}
          >
            <Header.Content>Your Posts</Header.Content>
          </Header>
          {message && <DNAMessage message={message} type="success" />}
          <Container textAlign="right">
            <Link href="/dashboard/post/new">
              <Button primary>
                New Post
                <Icon name="right chevron" />
              </Button>
            </Link>
          </Container>
          <PostPanel
            posts={list}
            onRemove={handleRemove}
            onRecover={handleRecover}
            onPermanentlyRemove={handlePermanentlyRemove}
          />
          {isLoading && (
            <Segment textAlign="center">
              <Loader inline active>
                Loading...
              </Loader>
            </Segment>
          )}
          {showMore && !isLoading && (
            <Segment textAlign="center">
              <Button color="blue" onClick={loadMore}>
                Load More
              </Button>
            </Segment>
          )}
        </>
      )}
    </div>
  );
}
Example #26
Source File: AddProductToTable.js    From Merch-Dropper-fe with MIT License 4 votes vote down vote up
AddProductToTable = (props, history) => {
  const classes = useStyles();
  const [stores, setStores] = useState("");
  const data = scalableData(props.garment);
  const [product, setProduct] = useState({
    productName: "",
    price: "",
    description: "",
    storeID: NaN,
    designId: props.design.designId,
    color: data.product.color,
    size: "",
    product_id: data.product.id,
    type: data.design.type
  });
  const [cost, setCost] = useState([])
  const [modalIsOpen, setIsOpen] = useState(false);
  function openModal() {
    setIsOpen(true);
  }
  //fetch stores on mount of logged in user
  // get currently logged in user data from localstorage
  //GET userID from this endpoint /api/users/email
  // save the userID
  // GET stores associated from logged in user from endpoint of stores/userID
  //setStore to that list

  useEffect(() => {
    async function getStores() {
      const { email } = JSON.parse(localStorage.getItem("profile"));
      const res = await axiosWithEnv().get(
        `/api/users/email/${email}`
      );
      console.log(res, "res1");
      const userID = res.data.id;
      const res2 = await axiosWithEnv().get(
        `/api/stores/user/${userID}`
      );
      console.log(res2, "res");
      setStores(res.data);
      setProduct(
      { 
        productName: "",
        price: "",
        description: "",        
        designId: props.design.designId,
        color: data.product.color,
        size: "",
        product_id: data.product.id,
        type: data.design.type,
        storeID:res2.data.id
      })
    }
    getStores();
    //get price of product from scalablepress
      
      axiosWithEnv().post('/api/products/price', {
        type: props.garment.printStyle,
        sides: {
          front: 1
        },
          products: [{
            id: "canvas-unisex-t-shirt",
            color: data.product.color,
            size: "med",
            quantity: 1}
          ]
      })
          .then(res => {
             setCost(res.data)
          })
          .catch(err => {
            console.log(err)
          })
  }, [cost.total]);
  

  const handleChange = event => {
    setProduct({
      ...product,
      size:"med",
      [event.target.name]: event.target.value
    });
  };

    //calculate profit per item
  const calcPrice = (e, baseCost = cost.total) => {
    if(product.price){
      return product.price - baseCost
    } else{
      return 0;
    }
  }

  const handleSubmit = async event => {
    event.preventDefault();
    openModal();
    addProduct(props.history, props.garment, product, props.design);
    // setProduct({ ...product,
    //   designID: props.garment.mockUrl.substring(102)
    // })
    // setTimeout(() => {
    //   props.history.push("/dashboard");
    // }, 800);
  };
  console.log(props.garment);
  
  // const shirtColor = props.garment.color;
  const shirtImage = props.garment.mockUrl;
 
  return (
    <div className={classes.addproductContainer}>
      <Modal
        className={classes.modal}
        isOpen={modalIsOpen}
        contentLabel="Modal"
      >
        <Segment className={classes.segment}>
          <Dimmer active>
            <Loader>Adding Product to Inventory</Loader>
          </Dimmer>
        </Segment>
      </Modal>
      <div className={classes.imgContainer}>
        <img
          src={shirtImage}
          className={classes.shirtImg}
          alt="shirt design preview"
        />
      </div>
      <div className={classes.formContainer}>
        <form onSubmit={handleSubmit} className={classes.form}>
          <TextField
            className={classes.createTitle}
            label="Create Title"
            name="productName"
            value={product.productName}
            onChange={handleChange}
            InputProps={{
              disableUnderline: true
            }}
            InputLabelProps={{
              classes: {
                root: classes.labelText
              }
            }}
          />{" "}
          <div className={classes.cost}>
          <TextField
            className={classes.price}
            label="$"
            name="price"
            value={product.price}
            onChange={handleChange}
            InputProps={{
              disableUnderline: true
            }}
            InputLabelProps={{
              classes: {
                root: classes.labelText
              }
            }}
          />{" "}
         <span className={classes.profit}>Profit per item:<strong> ${`${calcPrice().toFixed(2)}`}</strong></span>
          </div>
          <TextField
            className={classes.desc}
            label="Add Product Description"
            name="description"
            multiline
            rows={5}
            value={product.description}
            onChange={handleChange}
            InputProps={{
              disableUnderline: true
            }}
            InputLabelProps={{
              classes: {
                root: classes.labelText
              }
            }}
          />{" "}
          {/* <Typography
                              className={classes.productHeader}
                              variant="h3"
                              gutterBottom
                            >
                              Product:
                            </Typography>
                            <Typography className={classes.product} variant="body1" gutterBottom>
                              Unisex T - Shirt
                            </Typography> */}{" "}
          {/* <Typography className={classes.colorHeader} variant="h3" gutterBottom>
            Color:
          </Typography>{" "}
          <Typography className={classes.color} variant="body1" gutterBottom>
            {" "}
            {shirtColor}{" "}
          </Typography>{" "} */}
          {/* <TextField
                            select
                            className={classes.storeSelect}
                            name="storeID"
                            label="Select Store"
                            value={product.storeID}
                            onChange={handleChange}
                            InputProps={{ disableUnderline: true }}
                          >
                            {stores.map(store => (
                              <MenuItem key={store.id} value={store.id}>
                                {store.store_name}
                              </MenuItem>
                            ))}
                          </TextField> */}{" "}
          <Button
            variant="contained"
            className={classes.addButton}
            type="submit"
          >
            Add Product{" "}
          </Button>{" "}
        </form>{" "}
      </div>{" "}
    </div>
  );
}
Example #27
Source File: RailHeader.jsx    From react-chatengine-demo with MIT License 4 votes vote down vote up
RailHeader = () => {
  const { chatConfig } = useChat();
  const configResolved = useResolved(chatConfig);
  const inputRef = useRef(null);
  const [image, setImage] = useState();

  const onFileAttach = file => {
    setImage(file);
  };

  return (
    <>
      <input
        type="file"
        ref={inputRef}
        className="file-input"
        accept="image/jpeg,image/png"
        onChange={e => {
          const file = e.target?.files?.[0];
          if (file) {
            onFileAttach(file);
          }
        }}
      />

      {!!image && (
        <ImageUpload
          crop
          file={image}
          header="Set Your Avatar"
          mode="message"
          onSubmit={croppedImage => {
            const storageRef = fb.storage.ref();
            const uploadRef = storageRef.child(
              `${chatConfig.userSecret}_avatar.jpg`,
            );
            uploadRef.put(croppedImage).then(() => {
              uploadRef.getDownloadURL().then(url => {
                fb.firestore
                  .collection('chatUsers')
                  .doc(chatConfig.userSecret)
                  .update({ avatar: url })
                  .then(() => {
                    setImage(null);
                  });
              });
            });
          }}
          close={() => setImage(null)}
        />
      )}

      <div className="left-rail-header">
        <Icon
          onClick={() => fb.auth.signOut()}
          className="sign-out"
          name="sign out"
        />
        {configResolved && !!chatConfig ? (
          <div className="current-user-info">
            <IconGroup
              onClick={() => {
                const input = inputRef.current;
                if (input) {
                  input.value = '';
                  input.click();
                }
              }}
              className="user-avatar"
              size="large"
            >
              {chatConfig.avatar ? (
                <Image src={chatConfig.avatar} avatar />
              ) : (
                <div className="empty-avatar">
                  {chatConfig.userName[0].toUpperCase()}
                </div>
              )}

              <Icon corner name="camera" inverted circular />
            </IconGroup>

            <div className="current-username">@{chatConfig.userName}</div>
          </div>
        ) : (
          <div className="user-loading">
            <Loader active size="small" />
          </div>
        )}
      </div>
    </>
  );
}