mirror of
https://github.com/knadh/listmonk.git
synced 2024-11-10 17:13:04 +08:00
commit
d8d7f88af3
11 changed files with 108 additions and 44 deletions
|
@ -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!
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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", {
|
||||
|
|
|
@ -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" }}>
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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>{" "}
|
||||
{this.state.record.name} ({this.state.record.email})
|
||||
<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>
|
||||
|
|
|
@ -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>
|
||||
<Col span={15}>
|
||||
<Row>
|
||||
<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> </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>
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -240,7 +240,7 @@ td .ant-tag {
|
|||
justify-content: center;
|
||||
|
||||
min-height: 90px;
|
||||
|
||||
|
||||
padding: 10px;
|
||||
border: 1px solid #eee;
|
||||
overflow: hidden;
|
||||
|
@ -313,4 +313,62 @@ 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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue