Merge pull request #14 from knadh/feat-responsive

Responsive design
This commit is contained in:
Kailash Nadh 2019-09-10 12:56:40 +05:30 committed by GitHub
commit d8d7f88af3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 108 additions and 44 deletions

View file

@ -51,7 +51,6 @@ Alternatively, to run a demo of listmonk, you can quickly spin up a container `d
- User auth, management, permissions
- Ability to write raw campaign logs to a target
- Analytics views and reports
- Make Ant design UI components responsive
- Better widgets on dashboard
- Tests!

View file

@ -28,8 +28,8 @@ import Delta from "quill-delta"
import "react-quill/dist/quill.snow.css"
const formItemLayout = {
labelCol: { xs: { span: 16 }, sm: { span: 4 } },
wrapperCol: { xs: { span: 16 }, sm: { span: 10 } }
labelCol: { xs: { span: 16 }, sm: { span: 10 }, md: { span: 4 } },
wrapperCol: { xs: { span: 16 }, sm: { span: 14 }, md: { span: 10 } }
}
class Editor extends React.PureComponent {
@ -521,7 +521,7 @@ class TheFormDef extends React.PureComponent {
/>
)}
</Col>
<Col span={12}>
<Col xs={24} sm={2}>
{this.state.sendLater &&
getFieldDecorator("send_at", {
initialValue:
@ -656,7 +656,7 @@ class Campaign extends React.PureComponent {
return (
<section className="content campaign">
<Row>
<Col span={16}>
<Col xs={24} sm={16}>
{!this.state.record.id && <h1>Create a campaign</h1>}
{this.state.record.id && (
<div>
@ -675,7 +675,7 @@ class Campaign extends React.PureComponent {
</div>
)}
</Col>
<Col span={8} className="right">
<Col xs={24} sm={8} className="right header-action-break">
{!this.state.formDisabled && !this.state.loading && (
<div>
<Button

View file

@ -651,10 +651,10 @@ class Campaigns extends React.PureComponent {
return (
<section className="content campaigns">
<Row>
<Col span={22}>
<Col xs={24} sm={14}>
<h1>Campaigns</h1>
</Col>
<Col span={2}>
<Col xs={24} sm={10} className="right header-action-break">
<Link to="/campaigns/new">
<Button type="primary" icon="plus" role="link">
New campaign

View file

@ -45,16 +45,16 @@ class Dashboard extends React.PureComponent {
{this.state.stats && (
<div className="stats">
<Row>
<Col span={16}>
<Col xs={24} sm={24} xl={16}>
<Row gutter={24}>
<Col span={8}>
<Col xs={24} sm={12} md={8}>
<Card title="Active subscribers" bordered={false}>
<h1 className="count">
{this.orZero(this.state.stats.subscribers.enabled)}
</h1>
</Card>
</Col>
<Col span={8}>
<Col xs={24} sm={12} md={8}>
<Card title="Blacklisted subscribers" bordered={false}>
<h1 className="count">
{this.orZero(
@ -63,7 +63,7 @@ class Dashboard extends React.PureComponent {
</h1>
</Card>
</Col>
<Col span={8}>
<Col xs={24} sm={12} md={8}>
<Card title="Orphaned subscribers" bordered={false}>
<h1 className="count">
{this.orZero(this.state.stats.orphan_subscribers)}
@ -72,16 +72,16 @@ class Dashboard extends React.PureComponent {
</Col>
</Row>
</Col>
<Col span={6} offset={2}>
<Col xs={24} sm={24} xl={{ span: 6, offset: 2 }}>
<Row gutter={24}>
<Col span={12}>
<Col xs={24} sm={12}>
<Card title="Public lists" bordered={false}>
<h1 className="count">
{this.orZero(this.state.stats.lists.public)}
</h1>
</Card>
</Col>
<Col span={12}>
<Col xs={24} sm={12}>
<Card title="Private lists" bordered={false}>
<h1 className="count">
{this.orZero(this.state.stats.lists.private)}
@ -93,9 +93,9 @@ class Dashboard extends React.PureComponent {
</Row>
<hr />
<Row>
<Col span={16}>
<Col xs={24} sm={24} xl={16}>
<Row gutter={24}>
<Col span={12}>
<Col xs={24} sm={12}>
<Card
title="Campaign views (last 3 months)"
bordered={false}
@ -124,7 +124,7 @@ class Dashboard extends React.PureComponent {
</Chart>
</Card>
</Col>
<Col span={12}>
<Col xs={24} sm={12}>
<Card
title="Link clicks (last 3 months)"
bordered={false}
@ -156,7 +156,7 @@ class Dashboard extends React.PureComponent {
</Row>
</Col>
<Col span={6} offset={2}>
<Col xs={24} sm={12} xl={{ span: 6, offset: 2 }}>
<Card
title="Campaigns"
bordered={false}

View file

@ -101,8 +101,8 @@ class TheFormDef extends React.PureComponent {
const { getFieldDecorator } = this.props.form
const formItemLayout = {
labelCol: { xs: { span: 16 }, sm: { span: 4 } },
wrapperCol: { xs: { span: 16 }, sm: { span: 10 } }
labelCol: { sm: { span: 24 }, md: { span: 5 } },
wrapperCol: { sm: { span: 24 }, md: { span: 10 } }
}
const formItemTailLayout = {
@ -163,7 +163,7 @@ class TheFormDef extends React.PureComponent {
)}
<Form.Item
{...formItemLayout}
label="CSV column delimiter"
label="CSV delimiter"
extra="Default delimiter is comma"
>
{getFieldDecorator("delim", {

View file

@ -31,6 +31,13 @@ class Base extends React.Component {
this.setState({ collapsed });
};
componentDidMount() {
// For small screen devices collapse the menu by default.
if (window.screen.width < 768) {
this.setState({ collapsed: true });
}
};
render() {
return (
<Layout style={{ minHeight: "100vh" }}>

View file

@ -378,10 +378,10 @@ class Lists extends React.PureComponent {
return (
<section className="content">
<Row>
<Col span={22}>
<Col xs={12} sm={18}>
<h1>Lists ({this.props.data[cs.ModelLists].total}) </h1>
</Col>
<Col span={2}>
<Col xs={12} sm={6} className="right">
<Button
type="primary"
icon="plus"

View file

@ -357,7 +357,7 @@ class Subscriber extends React.PureComponent {
{this.state.record.id && (
<div>
<h1>
<Tag
<Tag className="subscriber-status"
color={
tagColors.hasOwnProperty(this.state.record.status)
? tagColors[this.state.record.status]
@ -366,7 +366,9 @@ class Subscriber extends React.PureComponent {
>
{this.state.record.status}
</Tag>{" "}
<span className="subscriber-name">
{this.state.record.name} ({this.state.record.email})
</span>
</h1>
<span className="text-small text-grey">
ID {this.state.record.id} / UUID {this.state.record.uuid}
@ -374,13 +376,13 @@ class Subscriber extends React.PureComponent {
</div>
)}
</Col>
<Col span={2} className="right">
<Col span={2} className="right subscriber-export">
<Tooltip title="Export data" placement="top">
<a
role="button"
href={"/api/subscribers/" + this.state.record.id + "/export"}
>
<Icon type="export" />
<Icon type="export" style={{ fontSize: "20px" }}/>
</a>
</Tooltip>
</Col>

View file

@ -583,10 +583,10 @@ class Subscribers extends React.PureComponent {
}
return (
<section className="content">
<section className="content subscribers">
<header className="header">
<Row>
<Col span={20}>
<Col xs={24} sm={14}>
<h1>
Subscribers
{this.props.data[cs.ModelSubscribers].total > 0 && (
@ -597,7 +597,7 @@ class Subscribers extends React.PureComponent {
)}
</h1>
</Col>
<Col span={2}>
<Col xs={24} sm={10} className="right header-action-break">
<Button
type="primary"
icon="plus"
@ -611,9 +611,9 @@ class Subscribers extends React.PureComponent {
<div className="subscriber-query">
<Row>
<Col span={10}>
<Col sm={24} md={10}>
<Row>
<Row>
<Col span={15}>
<label>Search subscribers</label>
<Input.Search
name="name"
@ -621,14 +621,12 @@ class Subscribers extends React.PureComponent {
enterButton
onSearch={this.handleSearch}
/>{" "}
</Col>
<Col span={8} offset={1}>
<label>&nbsp;</label>
<br />
</Row>
<Row style={{ marginTop: "10px" }}>
<a role="button" onClick={this.handleToggleQueryForm}>
<Icon type="setting" /> Advanced
</a>
</Col>
</Row>
</Row>
{this.state.queryFormVisible && (
<div className="advanced-query">
@ -684,7 +682,7 @@ class Subscribers extends React.PureComponent {
</div>
)}
</Col>
<Col span={14}>
<Col sm={24} md={{ span: 12, offset: 2 }} className="slc-subs-section">
{this.state.selectedRows.length > 0 && (
<nav className="table-options">
<p>
@ -706,7 +704,7 @@ class Subscribers extends React.PureComponent {
</span>
)}
</p>
<p>
<p class="slc-subs-actions">
<a role="button" onClick={this.handleToggleListsForm}>
<Icon type="bars" /> Manage lists
</a>

View file

@ -392,10 +392,10 @@ class Templates extends React.PureComponent {
return (
<section className="content templates">
<Row>
<Col span={22}>
<Col xs={24} sm={14}>
<h1>Templates ({this.props.data[cs.ModelTemplates].length}) </h1>
</Col>
<Col span={2}>
<Col xs={24} sm={10} className="right header-action-break">
<Button
type="primary"
icon="plus"

View file

@ -314,3 +314,61 @@ td .ant-tag {
.preview-modal .ant-modal-footer button:first-child {
display: none;
}
@media screen and (max-width: 1200px) {
.dashboard .ant-card {
margin-bottom: 20px;
}
}
@media screen and (max-width: 1023px) {
.ant-table-content {
overflow-x: auto;
}
.ant-table-thead > tr > th,
.ant-table-tbody > tr > td {
white-space: nowrap;
}
}
@media screen and (max-width: 768px) {
.ant-modal {
top: 0 !important;
}
hr {
margin: 20px 0;
}
.subscriber-query {
padding: 20px
}
.header-action-break {
text-align: left;
}
.subscribers.content .slc-subs-section .table-options {
margin-top: 20px;
padding-top: 20px;
border-top: 1px solid #f4f4f4;
}
.subscribers.content .slc-subs-actions a {
display: block;
margin-bottom: 5px;
}
.ant-modal.subscriber-modal .subscriber-export {
margin-top: 10px;
}
.ant-modal.subscriber-modal .subscriber-name {
display: block;
}
.dashboard {
margin: 24px 12px;
}
}