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 |
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 |
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 |
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 ? <> </> : quantifiableLabel(total !== 1)}
</Statistic.Label>
</Statistic>
);
}
Example #4
Source File: Layout.js From nextfeathers with Apache License 2.0 | 6 votes |
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 |
/**
* 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 |
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 |
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 |
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 |
// 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 |
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 |
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 |
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 |
/** 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 |
/** 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 |
/** 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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
//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 |
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 |
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>
</>
);
}