Compare commits

..

6 Commits

Author SHA1 Message Date
30ebc7d22d Reduce raised components
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-05-15 17:34:52 +00:00
49ccdbd8ab Removing all floats and replace with flex 2023-05-15 17:14:12 +00:00
57de689815 General UI enhancements 2023-05-15 16:27:22 +00:00
55325dfe8b Improved footer design 2023-05-15 16:12:55 +00:00
214b80b72c Improved handling of longer file names in object lists 2023-05-15 15:23:56 +00:00
084ae20664 Small UI tweaks 2023-05-15 15:11:18 +00:00
15 changed files with 135 additions and 124 deletions

View File

@ -4,6 +4,7 @@ import { Helmet } from 'react-helmet';
import { useDispatch, useSelector } from 'react-redux';
import { ToastContainer, toast } from 'react-toastify';
import { Grid, Divider, Icon, Container } from 'semantic-ui-react';
import styled, { createGlobalStyle } from 'styled-components';
import api from '../api';
import actions from '../actions';
@ -50,6 +51,17 @@ import DocsDoc from './docs/Doc';
import Root from './main/root';
const StyledContent = styled.div`
display: flex;
flex-direction: column;
min-height: 100vh;
`;
const GlobalStyle = createGlobalStyle`
body {
background-color: rgb(255, 251, 248);
}
`;
function App() {
const dispatch = useDispatch();
@ -92,10 +104,11 @@ function App() {
}, [dispatch, user, driftReady, syncedToDrift]);
return (
<div style={{display: 'flex', flexDirection: 'column', minHeight: '100vh'}}>
<StyledContent>
<GlobalStyle whiteColor />
<Helmet defaultTitle={utils.appName()} titleTemplate={`%s | ${utils.appName()}`} />
<NavBar />
<div style={{ flex: '1 0 0' }}>
<div style={{ flex: '1' }}>
<Routes>
<Route end path="/" element={isAuthenticated
? <Home />
@ -141,20 +154,19 @@ function App() {
<Divider hidden section />
</div>
<div style={{ background: 'rgb(240,240,240)', padding: '30px 0px' }}>
<div style={{ background: 'rgba(0,0,0,0.02)', padding: 10}}>
<Container>
<Grid>
<Grid.Column computer={8}>
<Link to="/"><img alt={`${utils.appName()} logo`} src={logo} style={{ width: '100px', paddingTop: 20, paddingBottom: 20 }} /></Link>
<Grid verticalAlign='middle' stackable columns={2}>
<Grid.Column>
<Link to="/"><img alt={`${utils.appName()} logo`} src={logo} style={{ width: '100px', opacity: 0.5 }} /></Link>
{import.meta.env.VITE_SOURCE_REPO_URL &&
<p style={{marginTop: 10}}><small>{utils.appName()} software is free and open-source. Contributions to the project are always welcome.
<p style={{marginTop: 5 }}><small>{utils.appName()} software is free and open-source.
<br />
<Icon name="code" /> <a href={import.meta.env.VITE_SOURCE_REPO_URL} target="_blank" rel="noopener noreferrer" className='umami--click--source-footer'>Project source homepage</a>
</small></p>
}
</Grid.Column>
<Grid.Column computer={8} textAlign="right">
<div style={{ paddingTop: 40 }}>
<Grid.Column textAlign="right" style={{ fontSize: 13 }}>
{import.meta.env.VITE_PATREON_URL &&
<p>
<Icon name='trophy' />
@ -165,8 +177,6 @@ function App() {
<Icon name='book' />
<a href='/docs' target='_blank' rel='noopener noreferrer'>Documentation</a>
</p>
<Divider />
<p>
<Icon name="file alternate outline" />
<Link to="/privacy">Privacy Policy</Link>
@ -175,13 +185,12 @@ function App() {
<Icon name="file alternate outline" />
<Link to="terms-of-use">Terms of Use</Link>
</p>
</div>
</Grid.Column>
</Grid>
</Container>
</div>
</div>
</StyledContent>
);
}

View File

@ -155,10 +155,11 @@ Welcome back <Button floated="right" onClick={onClose} basic content="Close" />
<Input autoFocus size="large" fluid name="email" type="text" value={email} onChange={e => setEmail(e.target.value)} placeholder='Email or username' />
</Form.Field>
<Form.Field>
<label>Password
<Link to="/password/forgotten" style={{ float: 'right' }} onClick={onClose}>Forgotten your password?</Link>
</label>
<label>Password</label>
<Input size="large" fluid name="password" type="password" value={password} onChange={e => setPassword(e.target.value)} placeholder='Password' />
<div style={{ display: 'flex', justifyContent: 'end' }}>
<Link to="/password/forgotten" onClick={onClose}>Forgotten your password?</Link>
</div>
</Form.Field>
<div className="ui hidden divider" />
<Form.Button type='submit' size="large" color="teal" fluid loading={loading}>Login</Form.Button>

View File

@ -77,7 +77,8 @@ const NewFeedMessage = connect(
)}
</div>
}
<Button.Group style={{marginTop: 10, float:'right'}}>
<div style={{ display: 'flex', justifyContent: 'end', marginTop: 10 }}>
<Button.Group>
{!noAttachments &&
<Dropdown
trigger={<Button size='small' icon='paperclip' content='Attach something' loading={attachmentUploading}/>}
@ -107,7 +108,7 @@ const NewFeedMessage = connect(
}
<Button disabled={posting} loading={posting} size='small' color='teal' icon='send' content={inReplyTo ? 'Post reply' : 'Post message'} onClick={createEntry}/>
</Button.Group>
<div style={{clear:'both'}} />
</div>
</>
);
});

View File

@ -18,21 +18,17 @@ function ProjectCard({ project }) {
<Card.Meta>{shorten(project.description)}</Card.Meta>
</Card.Content>
<Card.Content extra>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
<UserChip user={project.owner} />
<span style={{ float: 'right' }}>
{project.visibility === 'private'
? (
<span>
<Icon name="lock" /> Private
</span>
<div><Icon name="lock" /> Private</div>
)
: (
<span>
<Icon name="unlock" /> Public
</span>
<div><Icon name="unlock" /> Public</div>
)
}
</span>
</div>
</Card.Content>
</Card>
);

View File

@ -126,7 +126,7 @@ function Home() {
}
{(groups && groups.length) ?
<Card fluid className='joyride-groups'>
<Card fluid className='joyride-groups' style={{opacity: 0.8}}>
<Card.Content>
<Card.Header>Your groups</Card.Header>
@ -154,7 +154,7 @@ function Home() {
}
{(import.meta.env.VITE_PATREON_URL || import.meta.env.VITE_KOFI_URL) &&
<Card fluid color='blue'>
<Card fluid style={{opacity: 0.8}}>
<Card.Content>
<Card.Header><span role="img" aria-label="Dancer">🕺</span> Support {utils.appName()}</Card.Header>
<Card.Description>{utils.appName()} is offered free of charge, but costs money to run and build. If you get value out of {utils.appName()} you may like to consider supporting it.</Card.Description>
@ -181,15 +181,16 @@ function Home() {
{user && !loadingProjects && (!projects || !projects.length) &&
<div style={{textAlign: 'center'}}>
<h1>
<span role="img" aria-label="chequered flag">🚀</span> Let's get started, {user?.username}!
<span role="img" aria-label="chequered flag">🚀</span> Let's get started
</h1>
<Divider hidden/>
<Segment placeholder textAlign='center'>
<h3>On {utils.appName()} your patterns and files are stored in <strong><span role="img" aria-label="box">📦</span> projects</strong></h3>
<p>Projects can contain anything - from rough ideas or design experiments through to commissions and exhibitions. Treat them as if they were just weaving-related <span role="img" aria-label="folder">📁</span> folders on your computer.</p>
<h3>On {utils.appName()}, your patterns and files are stored in <strong><span role="img" aria-label="box">📦</span> projects</strong></h3>
<p>Projects can contain anything: from rough ideas or design experiments through to commissions and exhibitions. Treat them as if they were just <span role="img" aria-label="folder">📁</span> folders on your computer.</p>
<p><HelpLink className='joyride-help' link={`/docs/projects`} text='Learn more about projects' marginTop/></p>
<Divider />
<h4>Start by creating a new project. Don't worry, you can keep it private.</h4>
<p><HelpLink className='joyride-help' link={`/docs/projects`} text='Learn more about projects' marginTop/></p>
<Button className='joyride-createProject' as={Link} to="/projects/new" color="teal" icon="plus" content="Create a project" />
</Segment>

View File

@ -152,6 +152,7 @@ function Group() {
</Grid.Column>
<Grid.Column computer={12}>
<Segment>
{user ?
<>
{!utils.isInGroup(user, group._id) &&
@ -182,6 +183,7 @@ function Group() {
:
<Message>Please login to view or join this group.</Message>
}
</Segment>
</Grid.Column>
</Grid>
</div>

View File

@ -85,7 +85,7 @@ function Members() {
<div>
{loading && (!members || !members.length) && <Loader active inline="centered" />}
{!loading && utils.isGroupAdmin(user, group) &&
<Segment raised color='blue' style={{marginBottom: 30}}>
<Segment color='blue' style={{marginBottom: 30}}>
{(members && members.length === 1 && members[0]._id === user._id) ?
<Header>You're the only person in this group</Header>
:
@ -109,7 +109,7 @@ function Members() {
}
{requests?.length > 0 &&
<Segment raised color='green' style={{marginBottom:30}}>
<Segment color='green' style={{marginBottom:30}}>
<h3>You have membership requests</h3>
<p>The following users want to join {group.name}.</p>
<Table relaxed='very' basic='very'>
@ -135,15 +135,17 @@ function Members() {
<Card.Content>
<UserChip user={i.recipientUser} />
</Card.Content>
<Card.Content extra >
<Card.Content extra>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
<Label size='tiny' color='yellow' content='Invited' />
{utils.isGroupAdmin(user, group) &&
<Dropdown text='Options' style={{float:'right'}}>
<Dropdown text='Options'>
<Dropdown.Menu>
<Dropdown.Item icon='trash' content='Delete invitation' onClick={e => deleteInvitation(i)} />
</Dropdown.Menu>
</Dropdown>
}
</div>
</Card.Content>
</Card>
)}
@ -154,16 +156,18 @@ function Members() {
<Card.Meta style={{marginTop: 10}}>{m.bio}</Card.Meta>
</Card.Content>
<Card.Content extra >
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
{utils.isGroupAdmin(m, group) &&
<Label size='tiny' color='violet' icon='rocket' content='Admin' />
}
{utils.isGroupAdmin(user, group) && user._id !== m._id &&
<Dropdown text='Options' style={{float:'right'}}>
<Dropdown text='Options'>
<Dropdown.Menu>
<Dropdown.Item icon='ban' content='Kick' onClick={e => kickUser(m._id)} />
</Dropdown.Menu>
</Dropdown>
}
</div>
</Card.Content>
</Card>
)}

View File

@ -75,13 +75,16 @@ function Projects() {
<h2>Projects in this group</h2>
<p>This tab lists projects that members have made available to this group.</p>
{myProjects?.length > 0 && <>
<AddProject style={{float:'right'}} />
</>}
{myProjects?.length > 0 && <div style={{ display: 'flex', justifyContent: 'end' }}>
<AddProject />
</div>}
<Divider />
{projects?.length > 0 &&
<Input autoFocus style={{float:'right', marginRight: 5}} size='small' icon='search' value={projectFilter} onChange={e => dispatch(actions.groups.updateProjectFilter(e.target.value))} placeholder='Filter projects...' />
<div style={{ display: 'flex', justifyContent: 'end' }}>
<Input size='small' icon='search' value={projectFilter} onChange={e => dispatch(actions.groups.updateProjectFilter(e.target.value))} placeholder='Filter projects...' />
</div>
}
<Divider hidden clearing />
{projects?.length > 0 ?
<Card.Group itemsPerRow={3}>

View File

@ -112,7 +112,7 @@ function ObjectList({ compact }) {
: <div style={{ height: 40, width:40, backgroundImage: `url(${logoGreyShort})`, backgroundSize: '50px' }} />
)}
<div style={{flex: 1, marginLeft: 5}}>
<h3 style={{fontSize: 13, marginBottom: 0}}>{object.name}</h3>
<h3 style={{fontSize: 13, marginBottom: 0, wordBreak: 'break-all'}}>{object.name}</h3>
<Label size='mini' rounded>
{object.type === 'pattern' && <><Icon name='pencil' /> WIF pattern</>}
{object.type === 'file' &&
@ -166,7 +166,7 @@ function ObjectList({ compact }) {
)
}
<Card.Content>
<Card.Header style={{ wordBreak: 'break-all' }}>{object.name}</Card.Header>
<p style={{ wordBreak: 'break-all' }}>{object.name}</p>
</Card.Content>
</Card>
))}

View File

@ -117,9 +117,9 @@ function ObjectViewer() {
<>
<Helmet title={`${object.name || 'Project Item'} | ${project?.name || 'Project'}`} />
<span style={{float:'right'}}>
<div style={{ display: 'flex', justifyContent: 'end' }}>
{object.type === 'pattern' && (project.user === (user && user._id) || project.openSource || object.preview) && <>
<Dropdown icon={null} trigger={<Button size='tiny' secondary icon='download' content='Download pattern' loading={downloading} disabled={downloading}/>}>
<Dropdown icon={null} trigger={<Button size='small' secondary icon='download' content='Download pattern' loading={downloading} disabled={downloading}/>}>
<Dropdown.Menu>
{object.preview &&
<Dropdown.Item onClick={e => downloadDrawdownImage(object)} content='Download drawdown as an image' icon='file outline' />
@ -160,7 +160,7 @@ function ObjectViewer() {
</>
}
</span>
</div>
{editingName ?
<div style={{marginBottom: 5}}>

View File

@ -54,12 +54,6 @@ function Project() {
{project
&& (
<div>
{/*history.location?.state?.prevPath &&
<div style={{marginBottom:15}}>
<Button basic secondary onClick={e => history.goBack()} icon='arrow left' content='Go back' />
</div>
*/}
{wideBody() && project.owner &&
<>
<h3 style={{ marginBottom: 0 }}>
@ -76,14 +70,15 @@ function Project() {
<Card fluid>
<Card.Content>
<Card.Header style={{ marginBottom: 10 }}>
{project.visibility === 'private' && <span data-tooltip="This project is private"><Icon name="lock" /></span>}
{project.visibility === 'private' && <span data-tooltip="This project is private" data-position="right center"><Icon name="lock" /></span>}
{project.name}
</Card.Header>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
{project.owner && <UserChip user={project.owner} />}
{utils.canEditProject(user, project) &&
<Button style={{float:'right'}} basic size='mini' icon='cogs' content='Settings' as={Link} to={`/${fullName}/settings`} />
<Button basic size='mini' icon='cogs' content='Settings' as={Link} to={`/${fullName}/settings`} />
}
</div>
</Card.Content>
<Card.Content extra>
{editingDescription

View File

@ -64,7 +64,7 @@ function ProjectSettings() {
<HelpLink link={`/docs/projects#changing-the-project-s-settings`} />
<Divider hidden section />
<Divider hidden />
<Segment>
<h3>General settings</h3>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 22 KiB

View File

View File

@ -9,7 +9,6 @@ import { BrowserTracing } from '@sentry/tracing';
import 'react-toastify/dist/ReactToastify.css';
import 'pell/dist/pell.min.css';
import './index.css';
import reducers from './reducers';
import App from './components/App';