utils#isSignedIn JavaScript Examples

The following examples show how to use utils#isSignedIn. 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: index.js    From dstack-server with Apache License 2.0 4 votes vote down vote up
App = ({location, fetchUser, userData, userLoading, history: {push}, setSearch}: Props) => {
    const [loading, setLoading] = useState(true);
    const isInitialMount = useRef(true);

    useTracking();

    useEffect(() => {
        if (isSignedIn())
            fetchUser(
                () => {},
                () => {
                    setLoading(false);
                    push(routes.authLogin());
                }
            );
        else
            setLoading(false);
    }, []);

    useEffect(() => {
        if (isInitialMount.current) {
            isInitialMount.current = false;
        } else {
            setLoading(userLoading);
        }
    }, [userLoading]);

    useEffect(() => {
        setSearch('');
    }, [location.pathname]);

    return (
        <div className={css.app}>
            {!loading && (
                <Switch>
                    {isSignedIn() && userData && (
                        <Redirect
                            exact
                            from="/"
                            to={routes.stacks(userData.user)}
                        />
                    )}

                    <Redirect
                        exact
                        from="/"
                        to={routes.authLogin()}
                    />

                    <Route path={routes.authLogin()} component={Login}/>
                    <DefaultLayoutRoute path={routes.verifyUser()} component={ConfirmEmail}/>

                    {isSignedIn() && (
                        <Switch>
                            <DefaultLayoutRoute path={routes.notFound()} component={NotFound} />
                            <DefaultLayoutRoute path={routes.settings()} component={Settings} />
                            <DefaultLayoutRoute path={routes.dashboards()} component={Dashboards} />
                            <DefaultLayoutRoute path={routes.stacks()} component={Stacks} />
                        </Switch>
                    )}

                    {!isSignedIn() && (
                        <Switch>
                            <UnAuthorizedLayoutRoute path={routes.notFound()} component={NotFound} />
                            <UnAuthorizedLayoutRoute path={routes.dashboards()} component={Dashboards} />
                            <UnAuthorizedLayoutRoute path={routes.stacks()} component={Stacks} />
                        </Switch>
                    )}

                    <Redirect
                        to={routes.notFound()}
                    />
                </Switch>
            )}

            {loading && <DefaultLayout>
                <Loader />
            </DefaultLayout>}
        </div>
    );
}
Example #2
Source File: index.js    From dstack-server with Apache License 2.0 4 votes vote down vote up
Details = ({
    data,
    fetch,
    update,
    currentUser,
    deleteDashboard,
    insertCard,
    deleteCard,
    updateCard,
    requestStatus,
    loading,
}: Props) => {
    const {items, moveItem, setItems} = useContext(DnDGridContext);

    const {t} = useTranslation();
    const [isShowStacksModal, setIsShowStacksModal] = useState(false);
    const [titleValue, setTitleValue] = useState(data ? data.title : '');
    const [view, setView] = useState('grid');
    const {form, setForm, onChange} = useForm({});
    const [fields, setFields] = useState({});
    const prevData = usePrevious(data);
    const params = useParams();
    const {push} = useHistory();
    const isDidMount = useRef(true);
    const updateDebounce = useCallback(_debounce(update, 300), []);
    const cards = data?.cards;

    const setGridItems = cardsItems => setItems(cardsItems.map(card => ({id: card.index, card})));

    useEffect(() => {
        if (!data || data.id !== params.id)
            fetch(params.user, params.id);
        else
            setGridItems(cards);
    }, []);

    useEffect(() => {
        if (window)
            window.dispatchEvent(new Event('resize'));
    }, [view]);

    useEffect(() => {
        if (cards && !isEqual(prevData, data))
            setGridItems(cards);

        return () => setGridItems([]);
    }, [cards]);


    useEffect(() => {
        if (!prevData && data || (prevData && data && prevData.id !== data.id))
            setTitleValue(data.title);

        if ((!isEqual(prevData, data) || isDidMount.current) && data)
            parseParams();

        if (isDidMount.current)
            isDidMount.current = false;
    }, [data]);

    const onChangeTitle = event => {
        setTitleValue(event.target.value);

        updateDebounce({
            user: params.user,
            id: data.id,
            title: event.target.value,
        });
    };

    const moveCard = (indexFrom, indexTo) => {
        if (indexTo < 0 || indexFrom < 0)
            return;

        const {stack} = items[indexFrom].card;

        updateCard({
            user: params.user,
            dashboard: data.id,
            stack,
            index: indexTo,
        });

        moveItem(indexFrom, indexTo);
    };

    const onClickAdd = event => {
        event.preventDefault();
        setIsShowStacksModal(true);
    };

    const closeModal = () => setIsShowStacksModal(false);

    const onClickDelete = () => {
        deleteDashboard(
            {
                user: params.user,
                id: data.id,
            },

            () => {
                push(routes.dashboards(params.user));
            }
        );
    };

    const getDeleteCardAction = stack => () => {
        deleteCard({
            user: params.user,
            dashboard: data.id,
            stack,
        });
    };

    const getUpdateCardAction = stack => fields => {
        updateCard({
            user: params.user,
            dashboard: data.id,
            stack,
            ...fields,
        });
    };

    const addStacksToDashboard = stacks => {
        stacks.forEach((stack, index) => {
            insertCard({
                user: params.user,
                dashboard: params.id,
                stack,
                index: cards.length + index,
            });
        });
    };

    const parseParams = () => {
        if (!cards)
            return;

        const fields = cards.reduce((result, card) => {
            const cardFields = parseStackParams(get(card, 'head.attachments', [])) || {};

            Object.keys(cardFields).forEach(fieldName => {
                if (result[fieldName]) {
                    if (cardFields[fieldName].type === 'select') {
                        result[fieldName].options = unionBy(
                            result[fieldName].options,
                            cardFields[fieldName].options, 'value');
                    }

                    if (cardFields[fieldName].type === 'slider') {

                        result[fieldName].options = {
                            ...result[fieldName].options,
                            ...cardFields[fieldName].options,
                        };

                        result[fieldName].min = Math.min(result[fieldName].min, cardFields[fieldName].min);
                        result[fieldName].max = Math.max(result[fieldName].max, cardFields[fieldName].max);
                    }
                } else {
                    result[fieldName] = cardFields[fieldName];
                }
            });

            return result;
        }, {});

        const defaultFilterValues = Object.keys(fields).reduce((result, fieldName) => {
            if (fields[fieldName].type === 'select')
                result[fieldName] = fields[fieldName].options[0].value;

            if (fields[fieldName].type === 'slider')
                result[fieldName] = fields[fieldName].options[0];

            if (fields[fieldName].type === 'checkbox')
                result[fieldName] = false;

            return result;
        }, {});

        setForm(defaultFilterValues);
        setFields(fields);
    };

    const renderFilters = () => {
        if (!Object.keys(fields).length)
            return null;

        const hasSelectField = Object.keys(fields).some(key => fields[key].type === 'select');

        return (
            <Filters
                fields={fields}
                form={form}
                onChange={onChange}
                className={cx(css.filters, {'with-select': hasSelectField})}
            />
        );
    };

    if (loading)
        return <Loader />;

    if (requestStatus === 403)
        return <AccessForbidden>
            {t('youDontHaveAnAccessToThisDashboard')}.

            {isSignedIn() && (
                <Fragment>
                    <br />

                    <Link to={routes.dashboards(currentUser)}>
                        {t('goToMyDashboards')}
                    </Link>
                </Fragment>
            )}
        </AccessForbidden>;

    if (requestStatus === 404)
        return <NotFound>
            {t('theDashboardYouAreRookingForCouldNotBeFound')}
            {' '}
            {isSignedIn() && (
                <Fragment>
                    <Link to={routes.dashboards(currentUser)}>
                        {t('goToMyDashboards')}
                    </Link>.
                </Fragment>
            )}
        </NotFound>;

    if (!data)
        return null;

    return (
        <div className={css.details}>
            <div className={css.header}>
                <div className={css.title}>
                    <StretchTitleField
                        className={css.edit}
                        value={titleValue}
                        onChange={onChangeTitle}
                        readOnly={currentUser !== data.user}
                        placeholder={t('newDashboard')}
                    />

                    <span className={`mdi mdi-lock${data.private ? '' : '-open'}`} />
                </div>

                {/*<Button*/}
                {/*    className={css.pdf}*/}
                {/*    color="secondary"*/}
                {/*>*/}
                {/*    <span className="mdi mdi-download" />*/}
                {/*    PDF*/}
                {/*</Button>*/}

                {currentUser === data.user && <Dropdown
                    className={css.dropdown}

                    items={[
                        {
                            title: t('delete'),
                            onClick: onClickDelete,
                        },
                    ]}
                >
                    <Button
                        className={css['dropdown-button']}
                        color="secondary"
                    >
                        <span className="mdi mdi-dots-horizontal" />
                    </Button>
                </Dropdown>}
            </div>

            {Boolean(items.length) && (
                <Fragment>
                    <div className={css.section}>
                        <div className={css.fields}>
                            {renderFilters()}
                        </div>

                        <div className={css.controls}>
                            {currentUser === data.user && (
                                <a
                                    className={css.addButton}
                                    onClick={onClickAdd}
                                    href="#"
                                >
                                    <span className="mdi mdi-plus" />
                                    {t('addStack')}
                                </a>
                            )}

                            <ViewSwitcher
                                value={view}
                                className={css.viewSwitcher}
                                onChange={view => setView(view)}
                            />
                        </div>
                    </div>

                    <div className={cx(css.cards, view)}>
                        {items.map(item => (
                            currentUser === data.user
                                ? <DnDItem
                                    id={item.id}
                                    key={item.card.stack}
                                    onMoveItem={moveCard}
                                >
                                    <Card
                                        filters={form}
                                        deleteCard={getDeleteCardAction(item.card.stack)}
                                        data={item.card}
                                        type={view}
                                        updateCard={getUpdateCardAction(item.card.stack)}
                                    />
                                </DnDItem>

                                : <Card
                                    key={item.card.stack}
                                    filters={form}
                                    data={item.card}
                                    type={view}
                                />
                        ))}
                    </div>
                </Fragment>
            )}

            {!items.length && (
                <div className={css.empty}>
                    {t('thereAreNoStacksYet')} <br/>
                    {t('youCanSendStacksYouWantToBeHereLaterOrAddItRightNow')}

                    {currentUser === data.user && (
                        <Fragment>
                            {' '}

                            <a
                                className={css.addButton}
                                onClick={onClickAdd}
                                href="#"
                            >{t('addStack')}</a>.
                        </Fragment>
                    )}
                </div>
            )}

            {isShowStacksModal && <SelectStacks
                isShow={isShowStacksModal}
                onClose={closeModal}
                onAddStacks={addStacksToDashboard}
            />}
        </div>
    );
}
Example #3
Source File: index.js    From dstack-server with Apache License 2.0 4 votes vote down vote up
List = ({
    currentUser,
    createDashboard,
    creatingDashboard,
    fetchList,
    setSearch,
    setSearchPlaceholder,
    data,
    search,
    loading,
    requestStatus,
}: Props) => {
    const {user} = useParams();
    const {push} = useHistory();
    const {t} = useTranslation();

    const onChangeSearch = value => setSearch(value);

    useEffect(() => {
        fetchList(user);
    }, [user]);

    useEffect(() => {
        setSearchPlaceholder(t('findDashboard'));
        return () => setSearchPlaceholder(null);
    }, []);

    const getItems = () => {
        let items = [];

        if (data && data.length) {
            if (search.length)
                items = data.filter(i => i.title.indexOf(search) >= 0);
            else
                items = data;
        }

        return items;
    };

    const onClickAdd = () => {
        createDashboard(
            user,
            ({dashboard}) => push(routes.dashboardsDetails(user, dashboard.id)),
        );
    };

    const items = getItems();

    if (loading)
        return <Loader />;

    if (requestStatus === 404)
        return <NotFound>
            {t('theDashboardYouAreRookingForCouldNotBeFound')}
            {' '}
            {isSignedIn() && (
                <Fragment>
                    <Link to={routes.dashboards(currentUser)}>
                        {t('goToMyDashboards')}
                    </Link>.
                </Fragment>
            )}
        </NotFound>;

    return (
        <div className={css.list}>
            <div className={css.title}>
                {currentUser === user
                    ? t('myDashboards')
                    : t('dashboardsOf', {name: user})
                }

                {data && Boolean(data.length) && <span>{data.length}</span>}
            </div>

            {data && Boolean(data.length) && <SearchField
                placeholder={t('search')}
                className={css.search}
                showEverything
                size="small"
                value={search}
                onChange={onChangeSearch}
            />}

            <div className={css.grid}>
                {currentUser === user && (
                    <div
                        onClick={onClickAdd}
                        className={cx(css.add, {disabled: creatingDashboard})}
                    >
                        <div className={css.caption}>
                            <span className="mdi mdi-plus" />
                            {t('newDashboard')}
                        </div>
                    </div>
                )}

                {items.map((item, index) => (
                    <Item key={index} dashboard={item} />
                ))}
            </div>
        </div>
    );
}
Example #4
Source File: index.js    From dstack-server with Apache License 2.0 4 votes vote down vote up
Details = ({
    attachment,
    attachmentRequestStatus,
    fetchDetails,
    fetchFrame,
    downloadAttachment,
    clearDetails,
    update,
    data = {},
    listData = {},
    frame,
    frameRequestStatus,
    loading,
    requestStatus,
    currentUser,
}: Props) => {
    let parsedAttachmentIndex;

    const params = useParams();
    const {push} = useHistory();
    const location = useLocation();
    const searchParams = parseSearch(location.search);

    if (searchParams.a)
        parsedAttachmentIndex = parseInt(searchParams.a);

    const [attachmentIndex, setAttachmentIndex] = useState(parsedAttachmentIndex);
    const [selectedFrame, setSelectedFrame] = useState(searchParams.f);
    const [headId, setHeadId] = useState(null);

    const {t} = useTranslation();
    const didMountRef = useRef(false);
    const {form, setForm, onChange} = useForm({});
    const [fields, setFields] = useState({});
    const prevFrame = usePrevious(frame);

    const [isShowHowToModal, setIsShowHowToModal] = useState(false);
    const [isShowUploadModal, setIsShowUploadModal] = useState(false);
    const isFirstChangeSearch = useRef(false);

    const showHowToModal = event => {
        event.preventDefault();
        setIsShowHowToModal(true);
    };

    const hideHowToModal = () => setIsShowHowToModal(false);

    const onClickDownloadAttachment = event => {
        event.preventDefault();
        downloadAttachment(`${params.user}/${params.stack}`, selectedFrame || headId, attachmentIndex || 0);
    };

    useEffect(() => {
        if (isFirstChangeSearch.current) {
            let parsedAttachmentIndex;

            if (searchParams.a)
                parsedAttachmentIndex = parseInt(searchParams.a);

            if (parsedAttachmentIndex !== attachmentIndex)
                setAttachmentIndex(parsedAttachmentIndex);

            if (searchParams.f !== selectedFrame)
                setSelectedFrame(searchParams.f);

        } else {
            isFirstChangeSearch.current = true;
        }
    }, [location.search]);

    useEffect(() => {
        let searchParams = {};

        if (attachmentIndex)
            searchParams.a = attachmentIndex;

        if (selectedFrame && selectedFrame !== headId)
            searchParams.f = selectedFrame;

        const searchString = Object
            .keys(searchParams)
            .map(key => `${key}=${searchParams[key]}`)
            .join('&');

        if (location.search.replace('?', '') !== searchString)
            push({search: searchString.length ? `?${searchString}` : ''});
    }, [attachmentIndex, selectedFrame, headId]);

    const fetchData = () => {
        fetchDetails(params.user, params.stack);
    };

    useEffect(() => {
        if (!data.head || !listData || (data.head.id !== listData.head))
            fetchData();

        return () => clearDetails();
    }, []);

    const setHeadFrame = frameId => {
        update({
            stack: `${data.user}/${data.name}`,
            noUpdateStore: true,
            head: frameId,
        }, () => setHeadId(frameId));
    };

    useEffect(() => {
        if (selectedFrame)
            fetchFrame(params.user, params.stack, selectedFrame);
    }, [selectedFrame]);

    useEffect(() => {
        if ((!isEqual(prevFrame, frame) || !didMountRef.current) && frame)
            parseParams();
    }, [frame]);

    useEffect(() => {
        if (data && data.head)
            setHeadId(data.head.id);
    }, [data]);

    const onChangeFrame = frameId => {
        setSelectedFrame(frameId);
        setAttachmentIndex(undefined);
    };

    const findAttach = (form, attachmentIndex) => {
        const attachments = get(frame, 'attachments');
        const fields = Object.keys(form);

        if (!attachments)
            return;

        if (fields.length) {
            attachments.some((attach, index) => {
                let valid = true;

                fields.forEach(key => {
                    if (!attach.params || !isEqual(attach.params[key], form[key]))
                        valid = false;
                });

                if (valid && !(attachmentIndex === undefined && index === 0))
                    setAttachmentIndex(index);

                return valid;
            });
        }
    };

    const findAttachDebounce = useCallback(_debounce(findAttach, 300), [data, frame]);

    useEffect(() => {
        if (didMountRef.current)
            findAttachDebounce(form, attachmentIndex);
        else
            didMountRef.current = true;
    }, [form]);

    const parseParams = () => {
        const attachments = get(frame, 'attachments');

        if (!attachments || !attachments.length)
            return;

        const fields = parseStackParams(attachments);

        setFields(fields);

        if (attachmentIndex !== undefined) {
            if (attachments[attachmentIndex])
                setForm(attachments[attachmentIndex].params);
        } else
            setForm(attachments[0].params);

    };

    const renderFields = () => {
        if (!Object.keys(fields).length)
            return null;

        const hasSelectField = Object.keys(fields).some(key => fields[key].type === 'select');

        return (
            <Filters
                fields={fields}
                form={form}
                onChange={onChange}
                className={cx(css.filters, {'with-select': hasSelectField})}
            />
        );
    };

    if (loading)
        return <Loader />;

    if (requestStatus === 403)
        return <AccessForbidden>
            {t('youDontHaveAnAccessToThisStack')}.

            {isSignedIn() && (
                <Fragment>
                    <br />

                    <Link to={routes.stacks(currentUser)}>
                        {t('goToMyStacks')}
                    </Link>
                </Fragment>
            )}
        </AccessForbidden>;

    if (requestStatus === 404)
        return <NotFound>
            {t('theStackYouAreRookingForCouldNotBeFound')}
            {' '}
            {isSignedIn() && (
                <Fragment>
                    <Link to={routes.stacks(currentUser)}>
                        {t('goToMyStacks')}
                    </Link>.
                </Fragment>
            )}
        </NotFound>;

    const currentFrame = selectedFrame ? selectedFrame : get(data, 'head.id');

    return (
        <div className={css.details}>
            <Helmet>
                <title>dstack.ai | {params.user} | {params.stack}</title>
            </Helmet>

            <section className={css.section}>
                <div className={css.header}>
                    <div className={css.title}>
                        {data.name}
                        <span className={`mdi mdi-lock${data.private ? '' : '-open'}`} />
                    </div>

                    {data && data.user === currentUser && (
                        <Dropdown
                            className={css.dropdown}

                            items={[
                                {
                                    title: t('upload'),
                                    onClick: () => setIsShowUploadModal(true),
                                },
                            ]}
                        >
                            <Button
                                className={css['dropdown-button']}
                                color="secondary"
                            >
                                <span className="mdi mdi-dots-horizontal" />
                            </Button>
                        </Dropdown>
                    )}
                </div>

                <Frames
                    frames={get(data, 'frames', [])}
                    frame={currentFrame}
                    headId={headId}
                    onMarkAsHead={setHeadFrame}
                    onChange={onChangeFrame}
                    className={css.revisions}
                />

                {!frameRequestStatus && renderFields()}

                {attachment && (
                    <div className={css['attachment-head']}>
                        {attachment.description && (
                            <div className={css.description}>
                                <MarkdownRender source={attachment.description} />
                            </div>
                        )}

                        {attachment.type === 'text/csv' && (
                            <div className={css.actions}>
                                <a href="#" onClick={showHowToModal}>{t('useThisStackViaAPI')}</a>
                                {' '}
                                {t('or')}
                                {' '}
                                <a href="#" onClick={onClickDownloadAttachment}>{t('download')}</a>
                                {' '}
                                {attachment.length && (
                                    <span className={css.size}>({formatBytes(attachment.length)})</span>
                                )}
                            </div>
                        )}
                    </div>
                )}

                {attachmentRequestStatus === 404 || frameRequestStatus === 404 && (
                    <div className={css.empty}>{t('noMatch')}</div>
                )}

                {(frame && !attachmentRequestStatus && !frameRequestStatus) && (
                    <Attachment
                        className={css.attachment}
                        withLoader
                        stack={`${params.user}/${params.stack}`}
                        frameId={currentFrame}
                        id={attachmentIndex || 0}
                    />
                )}
            </section>

            <Upload
                stack={params.stack}
                isShow={isShowUploadModal}
                onClose={() => setIsShowUploadModal(false)}
                refresh={fetchData}
            />

            <Modal
                isShow={isShowHowToModal}
                withCloseButton
                onClose={hideHowToModal}
                size="big"
                title={t('howToFetchDataUsingTheAPI')}
                className={css.modal}
            >
                <HowToFetchData
                    data={{
                        stack: `${params.user}/${params.stack}`,
                        params: form,
                    }}

                    modalMode
                />
            </Modal>
        </div>
    );
}
Example #5
Source File: index.js    From dstack-server with Apache License 2.0 4 votes vote down vote up
List = ({
    requestStatus,
    setSearch,
    fetchList,
    data = [],
    loading,
    deleteStack,
    search,
    setSearchPlaceholder,
    match: {params: {user}},
    currentUser,
    startAppProgress,
    completeAppProgress,
    resetAppProgress,
}: Props) => {
    const {t} = useTranslation();
    const [deletingStack, setDeletingStack] = useState(null);
    const [isShowWelcomeModal, setIsShowWelcomeModal] = useState(false);
    const [isShowHowToModal, setIsShowHowToModal] = useState(false);
    const isInitialMount = useRef(true);

    const showWelcomeModal = () => setIsShowWelcomeModal(true);
    const onChangeSearch = value => setSearch(value);

    const hideWelcomeModal = () => {
        localStorage.setItem('welcome-modal-is-showing', true);
        setIsShowWelcomeModal(false);
    };

    useEffect(() => {
        if (isInitialMount.current) {
            isInitialMount.current = false;
        } else {
            if (!localStorage.getItem('welcome-modal-is-showing') && !loading && !data.length)
                showWelcomeModal();
        }
    }, [data]);

    const fetchData = () => {
        startAppProgress();
        fetchList(user, completeAppProgress);
    };

    useEffect(() => {
        fetchData();

        return () => {
            resetAppProgress();
        };
    }, [user]);

    useEffect(() => {
        setSearchPlaceholder(t('findStack'));
        return () => setSearchPlaceholder(null);
    }, []);

    const showHowToModal = event => {
        event.preventDefault();
        setIsShowHowToModal(true);
    };

    const hideHowToModal = () => setIsShowHowToModal(false);

    const deleteItem = () => {
        deleteStack(deletingStack);
        hideDeleteConfirmation();
    };

    const showDeleteConfirmation = name => setDeletingStack(name);
    const hideDeleteConfirmation = () => setDeletingStack(null);

    const getItems = () => {
        let items = [];

        if (data && data.length) {
            if (search.length)
                items = data.filter(i => i.name.indexOf(search) >= 0);
            else
                items = data;
        }

        return items;
    };

    const items = getItems();

    if (requestStatus === 404)
        return <NotFound>
            {t('theStackYouAreRookingForCouldNotBeFound')}
            {' '}
            {isSignedIn() && (
                <Fragment>
                    <Link to={routes.stacks(currentUser)}>
                        {t('goToMyStacks')}
                    </Link>.
                </Fragment>
            )}
        </NotFound>;

    return (
        <div className={css.list}>
            <Helmet>
                <title>dstack.ai | {user}</title>
            </Helmet>

            <div className={css.title}>
                {currentUser === user
                    ? t('stacks')
                    : t('stacksOf', {name: user})
                }

                {currentUser === user && (
                    <Upload
                        withButton
                        className={css.upload}
                        refresh={fetchData}
                    />
                )}
            </div>

            {loading && !Boolean(data.length) && <Loader />}

            {!loading && !data.length && (
                <div className={css.message}>
                    {user === currentUser
                        ? t('youHaveNoStacksYet')
                        : t('theUserHasNoStacksYetByName', {name: user})
                    }
                </div>
            )}

            {!loading && !Boolean(data.length) && currentUser === user && (
                <HowTo />
            )}

            {Boolean(data.length && items.length) && currentUser === user && (
                <div className={css.text}>
                    {t('youHaveStacks', {count: data.length})}
                    {' '}
                    <a href="#" onClick={showHowToModal}>{t('seeHowToGuide')}</a>.
                </div>
            )}

            {Boolean(data.length) && <SearchField
                placeholder={t('search')}
                className={css.search}
                showEverything
                size="small"
                value={search}
                onChange={onChangeSearch}
            />}

            {Boolean(data.length && items.length) && <div className={css.grid}>
                {items.map((item, index) => <Item
                    withLink
                    key={index}
                    data={item}
                    deleteAction={showDeleteConfirmation}
                />)}
            </div>}

            {Boolean(data.length && !items.length) && <div className={css.text}>
                {t('noStacksAreFoundedMatchedTheSearchCriteria')}
            </div>}

            <Modal
                isShow={Boolean(deletingStack)}
                onClose={hideDeleteConfirmation}
                size="confirmation"
                title={t('deleteStack')}
                className={css.modal}
            >
                <div className={css.description}>
                    {t('areYouSureYouWantToDelete', {name: deletingStack})}
                </div>

                <div className={css.buttons}>
                    <Button
                        variant="contained"
                        color="primary"
                        onClick={hideDeleteConfirmation}
                        className={css.button}
                    >{t('cancel')}</Button>

                    <Button
                        color="secondary"
                        variant="contained"
                        onClick={deleteItem}
                        className={css.button}
                    >{t('deleteStack')}</Button>
                </div>
            </Modal>

            {currentUser === user && (
                <Modal
                    isShow={isShowWelcomeModal}
                    onClose={hideWelcomeModal}
                    size="small"
                    title={`${t('welcomeToDStack')}?`}
                    className={css.modal}
                >
                    <div className={css.description}>{t('yourEmailWasSuccessfullyConfirmed')}</div>

                    <div className={css.buttons}>
                        <Button
                            variant="contained"
                            color="primary"
                            onClick={hideWelcomeModal}
                            className={css.button}
                        >{t('getStarted')}</Button>
                    </div>
                </Modal>
            )}

            <Modal
                isShow={isShowHowToModal}
                withCloseButton
                onClose={hideHowToModal}
                size="big"
                title={t('howToConnectYourDataWithDStack')}
                className={css.modal}
            >
                <HowTo modalMode />
            </Modal>
        </div>
    );
}
Example #6
Source File: index.js    From dstack-server with Apache License 2.0 4 votes vote down vote up
Header = ({
    setSearch,
    search,
    searchPlaceholder,
    logOut,
    className,
    userData,
    match: {params},
    history,
    toggleMenu,
}: Props) => {
    const {t} = useTranslation();

    let user = '';

    if (params && params.user)
        user = params.user;
    else if (userData && userData.user)
        user = userData.user;

    const onChangeSearch = value => setSearch(value);

    const logOutHandle = () => {
        logOut(() => history.push('/'));
    };

    const renderSearch = () => (
        <SearchField
            showEverything
            isDark
            placeholder={searchPlaceholder}
            className={css.search}
            size="small"
            value={search}
            onChange={onChangeSearch}
        />
    );

    return <div className={cx(css.header, className)}>
        {isSignedIn() && <div className={cx(css.menu, 'mdi mdi-menu')} onClick={toggleMenu} />}

        <Link to="/" className={css.logo}>
            <img width="129" height="35" src={logo} alt="logo"/>
        </Link>

        <Switch>
            <Route
                path={routes.auth()}

                render={() => (
                    <div className={css.title}>{t('stacks')}</div>
                )}
            />

            <Route
                exact
                path={routes.dashboards(user)}
                render={renderSearch}
            />

            <Route
                path={routes.dashboardsDetails(user)}

                render={() => (
                    <Link to={routes.dashboards(user)} className={css.back}>
                        <span className="mdi mdi-arrow-left" />
                        {userData && (userData.user === user)
                            ? t('backToDashboards')
                            : t('backToDashboardsOf', {name: user})
                        }
                    </Link>
                )}
            />

            <Route
                path={routes.stackDetails()}

                render={() => (
                    <Link to={routes.stacks(user)} className={css.back}>
                        <span className="mdi mdi-arrow-left" />
                        {userData && (userData.user === user)
                            ? t('backToMyStacks')
                            : t('backToStacksOF', {name: user})
                        }
                    </Link>
                )}
            />

            <Route
                exact
                path={routes.stacks(user)}
                render={renderSearch}
            />
        </Switch>

        {userData && <div className={css.user}>
            <Dropdown
                items={[
                    {
                        title: t('signOut'),
                        onClick: logOutHandle,
                    },
                ]}
            >
                <Avatar className={css.avatar} name={userData.user} />
            </Dropdown>
        </div>}
    </div>;
}
Example #7
Source File: index.js    From dstack-server with Apache License 2.0 4 votes vote down vote up
Sidebar = ({
    className, currentUser, isShow, toggleMenu, userLoading,
    fetchStacksList, startAppProgress, completeAppProgress,
}: Props) => {
    const {t} = useTranslation();
    const {path} = useRouteMatch();
    const params = useParams();
    const {pathname} = useLocation();
    const sidebarRef = useRef(null);

    useOnClickOutside(sidebarRef, () => isShow && toggleMenu());

    const getMenuItemClick = item => () => {
        if (isShow)
            toggleMenu();

        if (item.onClick)
            item.onClick();
    };

    const refreshStacks = () => {
        if (pathname === routes.stacks(params.user)) {
            startAppProgress();
            fetchStacksList(params.user, completeAppProgress);
        }
    };

    const menuItems = [
        {
            to: routes.stacks(currentUser),
            label: t('stacks'),

            isActive: () => (
                new RegExp(path).test(routes.stacks())
                && (!currentUser || (currentUser === params.user))
                && !new RegExp(path + '$').test(routes.dashboards())
            ),

            onClick: refreshStacks,
        },

        {
            to: routes.dashboards(currentUser),
            label: t('dashboards'),
        },

        {
            to: routes.settings(),
            label: t('settings'),
        },
    ];

    return <div className={cx(css.sidebar, className, {show: isShow})} ref={sidebarRef}>
        <div className={cx(css.close, 'mdi mdi-close')} onClick={toggleMenu} />

        <div className={css.logo}>
            <Link to="/">
                <img width="129" height="35" src={logo} alt="logo"/>
            </Link>
        </div>

        {isSignedIn() && !userLoading && <ul className={css.links}>
            {menuItems.map((item, index) => (
                <li key={index} className={css.item}>
                    <NavLink
                        onClick={getMenuItemClick(item)}
                        to={item.to}
                        activeClassName="active"
                        isActive={item.isActive}
                    >
                        <span className={css.label}>{item.label}</span>

                        {item.beta && <sub className={cx(css.sub, 'green-text')}>
                            {t('beta')}
                        </sub>}
                    </NavLink>
                </li>
            ))}

            <li className={css.item}>
                <a
                    href={config.DOCS_URL}
                    target="_blank"
                >
                    <span className={css.label}>{t('docs')}</span>
                </a>
            </li>
        </ul>}
    </div>;
}