Add custom theme overhaul

- Use 'config-overrides.js' with less loader to load ant.design's less files instead of the compiled css to override theme variables
- Change logo, favicon, and primary theme colours
- Add pageTitle() to App() to let components set page titles
- Move all notifications to bottomRight to avoid blocking action items on the UI
This commit is contained in:
Kailash Nadh 2018-11-03 17:53:22 +05:30
parent 5d099ab10c
commit ac8c7ed93b
20 changed files with 1582 additions and 263 deletions

View File

@ -0,0 +1,30 @@
const {injectBabelPlugin} = require("react-app-rewired");
const rewireLess = require("react-app-rewire-less");
module.exports = function override(config, env) {
config = injectBabelPlugin(
[
"import", {
libraryName: "antd",
libraryDirectory: "es",
style: true
}
], // change importing css to less
config,
);
config = rewireLess.withLoaderOptions({
modifyVars: {
"@font-family":
'"IBM Plex Sans", "Helvetica Neueue", "Segoe UI", "sans-serif"',
"@font-size-base": "15px",
"@primary-color": "#7f2aff",
"@shadow-1-up": "0 -2px 3px @shadow-color",
"@shadow-1-down": "0 2px 3px @shadow-color",
"@shadow-1-left": "-2px 0 3px @shadow-color",
"@shadow-1-right": "2px 0 3px @shadow-color",
"@shadow-2": "0 2px 6px @shadow-color"
},
javascriptEnabled: true,
})(config, env);
return config;
};

View File

@ -7,20 +7,31 @@
"axios": "^0.18.0", "axios": "^0.18.0",
"dayjs": "^1.7.5", "dayjs": "^1.7.5",
"react": "^16.4.1", "react": "^16.4.1",
"react-app-rewire-less": "^2.1.3",
"react-app-rewired": "^1.6.2",
"react-dom": "^16.4.1", "react-dom": "^16.4.1",
"react-quill": "^1.3.1", "react-quill": "^1.3.1",
"react-router": "^4.3.1", "react-router": "^4.3.1",
"react-router-dom": "^4.3.1", "react-router-dom": "^4.3.1",
"react-scripts": "1.1.4" "react-scripts": "1.1.4"
}, },
"scripts": { "xxscripts": {
"start": "react-scripts start", "start": "react-scripts start",
"build": "react-scripts build", "build": "react-scripts build",
"test": "react-scripts test --env=jsdom", "test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject" "eject": "react-scripts eject"
}, },
"theme": "./src/theme.js", "scripts": {
"start": "react-app-rewired start",
"build": "react-app-rewired build",
"test": "react-app-rewired test --env=jsdom",
"eject": "react-scripts eject"
},
"eslintConfig": { "eslintConfig": {
"extends": "react-app" "extends": "react-app"
},
"devDependencies": {
"babel-plugin-import": "^1.11.0",
"less-plugin-npm-import": "^2.1.0"
} }
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -5,9 +5,10 @@
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="theme-color" content="#000000"> <meta name="theme-color" content="#000000">
<script src="%PUBLIC_URL%/api/config.js" type="text/javascript"></script> <script src="%PUBLIC_URL%/api/config.js" type="text/javascript"></script>
<link href="https://fonts.googleapis.com/css?family=IBM+Plex+Sans:400,600" rel="stylesheet">
<link rel="manifest" href="%PUBLIC_URL%/manifest.json"> <link rel="manifest" href="%PUBLIC_URL%/manifest.json">
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico"> <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.png">
<title>React App</title> <title>%PUBLIC_URL%</title>
</head> </head>
<body> <body>
<noscript> <noscript>

View File

@ -112,12 +112,19 @@ class App extends React.PureComponent {
} }
} }
pageTitle = (title) => {
document.title = title
}
render() { render() {
return ( return (
<BrowserRouter> <BrowserRouter>
<Layout modelRequest={ this.modelRequest } <Layout
modelRequest={ this.modelRequest }
request={ this.request } request={ this.request }
reqStates={ this.state.reqStates } reqStates={ this.state.reqStates }
pageTitle={ this.pageTitle }
config={ window.CONFIG } config={ window.CONFIG }
data={ this.state.data } /> data={ this.state.data } />
</BrowserRouter> </BrowserRouter>

View File

@ -214,7 +214,7 @@ class TheFormDef extends React.PureComponent {
this.setState({ loading: true }) this.setState({ loading: true })
if(!this.props.isSingle) { if(!this.props.isSingle) {
this.props.modelRequest(cs.ModelCampaigns, cs.Routes.CreateCampaign, cs.MethodPost, values).then((resp) => { this.props.modelRequest(cs.ModelCampaigns, cs.Routes.CreateCampaign, cs.MethodPost, values).then((resp) => {
notification["success"]({ placement: "topRight", notification["success"]({ placement: cs.MsgPosition,
message: "Campaign created", message: "Campaign created",
description: `"${values["name"]}" created` }) description: `"${values["name"]}" created` })
@ -228,7 +228,7 @@ class TheFormDef extends React.PureComponent {
}) })
} else { } else {
this.props.modelRequest(cs.ModelCampaigns, cs.Routes.UpdateCampaign, cs.MethodPut, { ...values, id: this.props.record.id }).then((resp) => { this.props.modelRequest(cs.ModelCampaigns, cs.Routes.UpdateCampaign, cs.MethodPut, { ...values, id: this.props.record.id }).then((resp) => {
notification["success"]({ placement: "topRight", notification["success"]({ placement: cs.MsgPosition,
message: "Campaign updated", message: "Campaign updated",
description: `"${values["name"]}" updated` }) description: `"${values["name"]}" updated` })
this.setState({ loading: false }) this.setState({ loading: false })
@ -259,7 +259,7 @@ class TheFormDef extends React.PureComponent {
this.setState({ loading: true }) this.setState({ loading: true })
this.props.request(cs.Routes.TestCampaign, cs.MethodPost, values).then((resp) => { this.props.request(cs.Routes.TestCampaign, cs.MethodPost, values).then((resp) => {
this.setState({ loading: false }) this.setState({ loading: false })
notification["success"]({ placement: "topRight", notification["success"]({ placement: cs.MsgPosition,
message: "Test sent", message: "Test sent",
description: `Test messages sent` }) description: `Test messages sent` })
}).catch(e => { }).catch(e => {
@ -278,6 +278,12 @@ class TheFormDef extends React.PureComponent {
subLists = record.lists.map((v) => { return v.id !== 0 ? v.id : null }).filter(v => v !== null) subLists = record.lists.map((v) => { return v.id !== 0 ? v.id : null }).filter(v => v !== null)
} }
if(this.record) {
this.props.pageTitle(record.name + " / Campaigns")
} else {
this.props.pageTitle("New campaign")
}
return ( return (
<div> <div>
<Spin spinning={ this.state.loading }> <Spin spinning={ this.state.loading }>

View File

@ -248,6 +248,7 @@ class Campaigns extends React.PureComponent {
} }
componentDidMount() { componentDidMount() {
this.props.pageTitle("Campaigns")
dayjs.extend(relativeTime) dayjs.extend(relativeTime)
this.fetchRecords() this.fetchRecords()
} }

View File

@ -1,7 +1,9 @@
import React from 'react'; import React from 'react';
import 'antd/dist/antd.css';
class Dashboard extends React.Component { class Dashboard extends React.PureComponent {
componentDidMount = () => {
this.props.pageTitle("Dashboard")
}
render() { render() {
return ( return (
<h1>Welcome</h1> <h1>Welcome</h1>

View File

@ -262,6 +262,7 @@ class Import extends React.PureComponent {
} }
componentDidMount() { componentDidMount() {
this.props.pageTitle("Import subscribers")
this.fetchimportState() this.fetchimportState()
} }
render() { render() {

View File

@ -3,7 +3,7 @@ import { Switch, Route } from "react-router-dom"
import { Link } from "react-router-dom" import { Link } from "react-router-dom"
import { Layout, Menu, Icon } from "antd" import { Layout, Menu, Icon } from "antd"
import "antd/dist/antd.css" // import "antd/dist/antd.css"
import logo from "./static/listmonk.svg" import logo from "./static/listmonk.svg"
// Views. // Views.
@ -17,6 +17,7 @@ import Campaigns from "./Campaigns";
import Campaign from "./Campaign"; import Campaign from "./Campaign";
import Media from "./Media"; import Media from "./Media";
const { Content, Footer, Sider } = Layout const { Content, Footer, Sider } = Layout
const SubMenu = Menu.SubMenu const SubMenu = Menu.SubMenu
@ -30,7 +31,7 @@ class Base extends React.Component {
onCollapse = (collapsed) => { onCollapse = (collapsed) => {
this.setState({ collapsed }) this.setState({ collapsed })
} }
render() { render() {
return ( return (
<Layout style={{ minHeight: "100vh" }}> <Layout style={{ minHeight: "100vh" }}>

View File

@ -23,7 +23,7 @@ class CreateFormDef extends React.PureComponent {
if (this.props.formType === cs.FormCreate) { if (this.props.formType === cs.FormCreate) {
// Create a new list. // Create a new list.
this.props.modelRequest(cs.ModelLists, cs.Routes.CreateList, cs.MethodPost, values).then(() => { this.props.modelRequest(cs.ModelLists, cs.Routes.CreateList, cs.MethodPost, values).then(() => {
notification["success"]({ placement: "topRight", message: "List created", description: `"${values["name"]}" created` }) notification["success"]({ placement: cs.MsgPosition, message: "List created", description: `"${values["name"]}" created` })
this.props.fetchRecords() this.props.fetchRecords()
this.props.onClose() this.props.onClose()
this.setState({ modalWaiting: false }) this.setState({ modalWaiting: false })
@ -34,7 +34,7 @@ class CreateFormDef extends React.PureComponent {
} else { } else {
// Edit a list. // Edit a list.
this.props.modelRequest(cs.ModelLists, cs.Routes.UpdateList, cs.MethodPut, { ...values, id: this.props.record.id }).then(() => { this.props.modelRequest(cs.ModelLists, cs.Routes.UpdateList, cs.MethodPut, { ...values, id: this.props.record.id }).then(() => {
notification["success"]({ placement: "topRight", message: "List modified", description: `"${values["name"]}" modified` }) notification["success"]({ placement: cs.MsgPosition, message: "List modified", description: `"${values["name"]}" modified` })
this.props.fetchRecords() this.props.fetchRecords()
this.props.onClose() this.props.onClose()
this.setState({ modalWaiting: false }) this.setState({ modalWaiting: false })
@ -111,7 +111,7 @@ class Lists extends React.PureComponent {
title: "Name", title: "Name",
dataIndex: "name", dataIndex: "name",
sorter: true, sorter: true,
width: "50%", width: "40%",
render: (text, record) => { render: (text, record) => {
const out = []; const out = [];
out.push( out.push(
@ -130,7 +130,7 @@ class Lists extends React.PureComponent {
{ {
title: "Type", title: "Type",
dataIndex: "type", dataIndex: "type",
width: "5%", width: "10%",
render: (type, _) => { render: (type, _) => {
let color = type === "private" ? "orange" : "green" let color = type === "private" ? "orange" : "green"
return <Tag color={color}>{type}</Tag> return <Tag color={color}>{type}</Tag>
@ -139,8 +139,13 @@ class Lists extends React.PureComponent {
{ {
title: "Subscribers", title: "Subscribers",
dataIndex: "subscriber_count", dataIndex: "subscriber_count",
width: "10%", width: "15%",
align: "center" align: "center",
render: (text, record) => {
return(
<div className="name" key={`name-${record.id}`}><Link to={ `/subscribers/lists/${record.id}` }>{ text }</Link></div>
)
}
}, },
{ {
title: "Created", title: "Created",
@ -175,6 +180,7 @@ class Lists extends React.PureComponent {
} }
componentDidMount() { componentDidMount() {
this.props.pageTitle("Lists")
this.fetchRecords() this.fetchRecords()
} }
@ -185,7 +191,7 @@ class Lists extends React.PureComponent {
deleteRecord = (record) => { deleteRecord = (record) => {
this.props.modelRequest(cs.ModelLists, cs.Routes.DeleteList, cs.MethodDelete, { id: record.id }) this.props.modelRequest(cs.ModelLists, cs.Routes.DeleteList, cs.MethodDelete, { id: record.id })
.then(() => { .then(() => {
notification["success"]({ placement: "topRight", message: "List deleted", description: `"${record.name}" deleted` }) notification["success"]({ placement: cs.MsgPosition, message: "List deleted", description: `"${record.name}" deleted` })
// Reload the table. // Reload the table.
this.fetchRecords() this.fetchRecords()

View File

@ -8,6 +8,7 @@ class TheFormDef extends React.PureComponent {
} }
componentDidMount() { componentDidMount() {
this.props.pageTitle("Media")
this.fetchRecords() this.fetchRecords()
} }
@ -18,7 +19,7 @@ class TheFormDef extends React.PureComponent {
handleDeleteRecord = (record) => { handleDeleteRecord = (record) => {
this.props.modelRequest(cs.ModelMedia, cs.Routes.DeleteMedia, cs.MethodDelete, { id: record.id }) this.props.modelRequest(cs.ModelMedia, cs.Routes.DeleteMedia, cs.MethodDelete, { id: record.id })
.then(() => { .then(() => {
notification["success"]({ placement: "topRight", message: "Image deleted", description: `"${record.filename}" deleted` }) notification["success"]({ placement: cs.MsgPosition, message: "Image deleted", description: `"${record.filename}" deleted` })
// Reload the table. // Reload the table.
this.fetchRecords() this.fetchRecords()

View File

@ -1,4 +1,5 @@
import React from "react" import React from "react"
import { Link } from "react-router-dom"
import { Row, Col, Modal, Form, Input, Select, Button, Table, Icon, Tooltip, Tag, Popconfirm, Spin, notification } from "antd" import { Row, Col, Modal, Form, Input, Select, Button, Table, Icon, Tooltip, Tag, Popconfirm, Spin, notification } from "antd"
import Utils from "./utils" import Utils from "./utils"
@ -233,9 +234,21 @@ class Subscribers extends React.PureComponent {
sorter: true, sorter: true,
width: "25%", width: "25%",
render: (text, record) => { render: (text, record) => {
return (
<a role="button" onClick={() => this.handleShowEditForm(record)}>{text}</a> const out = [];
out.push(
<div key={`sub-email-${ record.id }`} className="sub-name">
<a role="button" onClick={() => { this.handleShowEditForm(record)}}>{text}</a>
</div>
) )
if(record.lists.length > 0) {
for (let i = 0; i < record.lists.length; i++) {
out.push(<Tag className="list" key={`sub-${ record.id }-list-${ record.lists[i].id }`}><Link to={ `/subscribers/lists/${ record.lists[i].id }` }>{ record.lists[i].name }</Link></Tag>)
}
}
return out
} }
}, },
{ {
@ -406,6 +419,12 @@ class Subscribers extends React.PureComponent {
...this.state.queryParams ...this.state.queryParams
} }
if(this.state.queryParams.list) {
this.props.pageTitle(this.state.queryParams.list.name + " / Subscribers")
} else {
this.props.pageTitle("Subscribers")
}
return ( return (
<section className="content"> <section className="content">
<header className="header"> <header className="header">

View File

@ -25,7 +25,7 @@ class CreateFormDef extends React.PureComponent {
if (this.props.formType === cs.FormCreate) { if (this.props.formType === cs.FormCreate) {
// Create a new list. // Create a new list.
this.props.modelRequest(cs.ModelTemplates, cs.Routes.CreateTemplate, cs.MethodPost, values).then(() => { this.props.modelRequest(cs.ModelTemplates, cs.Routes.CreateTemplate, cs.MethodPost, values).then(() => {
notification["success"]({ placement: "topRight", message: "Template added", description: `"${values["name"]}" added` }) notification["success"]({ placement: cs.MsgPosition, message: "Template added", description: `"${values["name"]}" added` })
this.props.fetchRecords() this.props.fetchRecords()
this.props.onClose() this.props.onClose()
this.setState({ modalWaiting: false }) this.setState({ modalWaiting: false })
@ -36,7 +36,7 @@ class CreateFormDef extends React.PureComponent {
} else { } else {
// Edit a list. // Edit a list.
this.props.modelRequest(cs.ModelTemplates, cs.Routes.UpdateTemplate, cs.MethodPut, { ...values, id: this.props.record.id }).then(() => { this.props.modelRequest(cs.ModelTemplates, cs.Routes.UpdateTemplate, cs.MethodPut, { ...values, id: this.props.record.id }).then(() => {
notification["success"]({ placement: "topRight", message: "Template updated", description: `"${values["name"]}" modified` }) notification["success"]({ placement: cs.MsgPosition, message: "Template updated", description: `"${values["name"]}" modified` })
this.props.fetchRecords() this.props.fetchRecords()
this.props.onClose() this.props.onClose()
this.setState({ modalWaiting: false }) this.setState({ modalWaiting: false })
@ -196,6 +196,7 @@ class Templates extends React.PureComponent {
} }
componentDidMount() { componentDidMount() {
this.props.pageTitle("Templates")
this.fetchRecords() this.fetchRecords()
} }
@ -206,7 +207,7 @@ class Templates extends React.PureComponent {
handleDeleteRecord = (record) => { handleDeleteRecord = (record) => {
this.props.modelRequest(cs.ModelTemplates, cs.Routes.DeleteTemplate, cs.MethodDelete, { id: record.id }) this.props.modelRequest(cs.ModelTemplates, cs.Routes.DeleteTemplate, cs.MethodDelete, { id: record.id })
.then(() => { .then(() => {
notification["success"]({ placement: "topRight", message: "Template deleted", description: `"${record.name}" deleted` }) notification["success"]({ placement: cs.MsgPosition, message: "Template deleted", description: `"${record.name}" deleted` })
// Reload the table. // Reload the table.
this.fetchRecords() this.fetchRecords()
@ -218,7 +219,7 @@ class Templates extends React.PureComponent {
handleSetDefault = (record) => { handleSetDefault = (record) => {
this.props.modelRequest(cs.ModelTemplates, cs.Routes.SetDefaultTemplate, cs.MethodPut, { id: record.id }) this.props.modelRequest(cs.ModelTemplates, cs.Routes.SetDefaultTemplate, cs.MethodPut, { id: record.id })
.then(() => { .then(() => {
notification["success"]({ placement: "topRight", message: "Template updated", description: `"${record.name}" set as default` }) notification["success"]({ placement: cs.MsgPosition, message: "Template updated", description: `"${record.name}" set as default` })
// Reload the table. // Reload the table.
this.fetchRecords() this.fetchRecords()

View File

@ -27,6 +27,7 @@ export const FormEdit = "edit"
export const MsgSuccess = "success" export const MsgSuccess = "success"
export const MsgWarning = "warning" export const MsgWarning = "warning"
export const MsgError = "error" export const MsgError = "error"
export const MsgPosition = "bottomRight"
// Model specific. // Model specific.
export const CampaignStatusColors = { export const CampaignStatusColors = {

View File

@ -4,6 +4,10 @@
transition: none !important; transition: none !important;
} }
body {
font-weight: 400;
}
header.header { header.header {
margin-bottom: 30px; margin-bottom: 30px;
} }
@ -54,7 +58,7 @@ body {
} }
.logo img { .logo img {
width: auto; width: auto;
height: 22px; height: 28px;
} }
.ant-layout-sider.ant-layout-sider-collapsed .logo a { .ant-layout-sider.ant-layout-sider-collapsed .logo a {
@ -75,10 +79,13 @@ td.actions {
text-align: right; text-align: right;
} }
td .ant-tag {
margin-top: 5px;
}
/* Templates */ /* Templates */
.wysiwyg { .wysiwyg {
padding: 30px; padding: 30px;
color: red;
} }
/* Subscribers */ /* Subscribers */

View File

@ -9,9 +9,9 @@
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="41.535763mm" width="45.041653mm"
height="8.3702965mm" height="9.8558731mm"
viewBox="0 0 41.535763 8.3702965" viewBox="0 0 45.041653 9.8558733"
version="1.1" version="1.1"
id="svg8" id="svg8"
sodipodi:docname="listmonk.svg" sodipodi:docname="listmonk.svg"
@ -25,9 +25,9 @@
borderopacity="1.0" borderopacity="1.0"
inkscape:pageopacity="0.0" inkscape:pageopacity="0.0"
inkscape:pageshadow="2" inkscape:pageshadow="2"
inkscape:zoom="1" inkscape:zoom="4"
inkscape:cx="41.789813" inkscape:cx="71.96648"
inkscape:cy="42.352202" inkscape:cy="2.639304"
inkscape:document-units="mm" inkscape:document-units="mm"
inkscape:current-layer="layer1" inkscape:current-layer="layer1"
showgrid="false" showgrid="false"
@ -56,66 +56,56 @@
inkscape:label="Layer 1" inkscape:label="Layer 1"
inkscape:groupmode="layer" inkscape:groupmode="layer"
id="layer1" id="layer1"
transform="translate(-88.728827,-97.568868)"> transform="translate(-12.438455,-21.535559)">
<g <path
aria-label="listmonk" style="fill:#ffcc00;fill-opacity:1;stroke:none;stroke-width:2.11094689;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
style="font-style:normal;font-weight:normal;font-size:8.44721699px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.21118042" d="m 16.660914,21.535559 a 4.2220837,4.2220837 0 0 0 -4.222459,4.222437 4.2220837,4.2220837 0 0 0 0.490699,1.968681 c 0.649637,-1.386097 2.059696,-2.343758 3.73176,-2.343758 1.672279,0 3.082188,0.958029 3.731731,2.344413 a 4.2220837,4.2220837 0 0 0 0.490039,-1.969336 4.2220837,4.2220837 0 0 0 -4.22177,-4.222437 z"
id="text817"> id="circle920"
<path inkscape:connector-curvature="0"
d="m 98.79092,104.90855 h 0.76025 v -6.3861 h -0.76025 z" inkscape:export-filename="/home/kailash/Site/listmonk/static/logo.png"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Avenir LT Std';-inkscape-font-specification:'Avenir LT Std Semi-Bold';fill:#000000;stroke-width:0.21118042" inkscape:export-xdpi="96"
id="path944" /> inkscape:export-ydpi="96" />
<path <flowRoot
d="m 100.82023,104.90855 h 0.76025 v -4.00398 h -0.76025 z m -0.17739,-5.440011 c 0,0.3041 0.25342,0.557521 0.55752,0.557521 0.3041,0 0.55751,-0.253421 0.55751,-0.557521 0,-0.3041 -0.25341,-0.557517 -0.55751,-0.557517 -0.3041,0 -0.55752,0.253417 -0.55752,0.557517 z" xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Avenir LT Std';-inkscape-font-specification:'Avenir LT Std Semi-Bold';fill:#000000;stroke-width:0.21118042" id="flowRoot935"
id="path946" /> style="font-style:normal;font-weight:normal;font-size:40px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
<path transform="matrix(0.27888442,0,0,0.27888442,92.852428,101.67857)"><flowRegion
d="m 105.51042,101.46208 c -0.28721,-0.47304 -0.83628,-0.65888 -1.36845,-0.65888 -0.7518,0 -1.5205,0.39702 -1.5205,1.23329 0,0.7687 0.57441,0.97988 1.22485,1.14038 0.32944,0.076 0.96298,0.16049 0.96298,0.61664 0,0.34634 -0.42236,0.50684 -0.81093,0.50684 -0.43926,0 -0.72646,-0.22808 -0.97143,-0.47305 l -0.57441,0.47305 c 0.39701,0.54062 0.88695,0.70956 1.54584,0.70956 0.79403,0 1.62186,-0.35478 1.62186,-1.25863 0,-0.7518 -0.50683,-1.00522 -1.16571,-1.16572 -0.33789,-0.076 -1.02212,-0.1436 -1.02212,-0.62509 0,-0.28721 0.31255,-0.4477 0.66733,-0.4477 0.38013,0 0.64199,0.17739 0.81938,0.39701 z" id="flowRegion937"><rect
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Avenir LT Std';-inkscape-font-specification:'Avenir LT Std Semi-Bold';fill:#000000;stroke-width:0.21118042" id="rect939"
id="path948" /> width="338"
<path height="181"
d="m 108.68116,100.90457 h -1.08969 v -1.123484 h -0.76025 v 1.123484 h -0.87851 v 0.65888 h 0.87851 v 2.08646 c 0,0.64199 0.0169,1.36 1.19106,1.36 0.15205,0 0.50683,-0.0338 0.68422,-0.13515 v -0.69267 c -0.15205,0.0929 -0.36323,0.11826 -0.54062,0.11826 -0.57441,0 -0.57441,-0.47305 -0.57441,-0.92075 v -1.81615 h 1.08969 z" x="-374"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Avenir LT Std';-inkscape-font-specification:'Avenir LT Std Semi-Bold';fill:#000000;stroke-width:0.21118042" y="-425.36423" /></flowRegion><flowPara
id="path950" /> id="flowPara941" /></flowRoot> <text
<path id="text874-8"
d="m 109.65378,104.90855 h 0.76025 v -2.07802 c 0,-0.90385 0.48994,-1.31776 1.039,-1.31776 0.73491,0 0.84473,0.54062 0.84473,1.30087 v 2.09491 h 0.76025 v -2.18783 c 0,-0.70957 0.2872,-1.20795 1.02211,-1.20795 0.73491,0 0.86162,0.55751 0.86162,1.16571 v 2.23007 h 0.76024 v -2.33144 c 0,-0.8954 -0.2872,-1.77391 -1.52049,-1.77391 -0.4815,0 -1.00522,0.25342 -1.26709,0.74335 -0.25341,-0.48993 -0.65888,-0.74335 -1.25018,-0.74335 -0.71802,0 -1.20796,0.48994 -1.28398,0.72646 h -0.0169 v -0.62509 h -0.70956 z" y="30.29347"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Avenir LT Std';-inkscape-font-specification:'Avenir LT Std Semi-Bold';fill:#000000;stroke-width:0.21118042" x="23.133614"
id="path952" /> style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-size:8.70788765px;line-height:1.25;font-family:'IBM Plex Sans';-inkscape-font-specification:'IBM Plex Sans, Medium';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.0459737"
<path xml:space="preserve"
d="m 117.46376,102.90656 c 0,-0.81094 0.50683,-1.39379 1.31776,-1.39379 0.81094,0 1.31777,0.58285 1.31777,1.39379 0,0.81093 -0.50683,1.39379 -1.31777,1.39379 -0.81093,0 -1.31776,-0.58286 -1.31776,-1.39379 z m -0.81094,0 c 0,1.16571 0.93765,2.10335 2.1287,2.10335 1.19106,0 2.1287,-0.93764 2.1287,-2.10335 0,-1.16572 -0.93764,-2.10336 -2.1287,-2.10336 -1.19105,0 -2.1287,0.93764 -2.1287,2.10336 z" inkscape:export-filename="/home/kailash/Site/listmonk/static/logo.png"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Avenir LT Std';-inkscape-font-specification:'Avenir LT Std Semi-Bold';fill:#000000;stroke-width:0.21118042" inkscape:export-xdpi="96"
id="path954" /> inkscape:export-ydpi="96"><tspan
<path style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:8.70788765px;font-family:'Avenir LT Std';-inkscape-font-specification:'Avenir LT Std Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.0459737"
d="m 121.86265,104.90855 h 0.76024 v -2.06112 c 0,-0.9292 0.4815,-1.33466 1.11504,-1.33466 0.48149,0 0.9123,0.27875 0.9123,1.03056 v 2.36522 h 0.76025 v -2.5764 c 0,-1.06435 -0.67578,-1.52895 -1.45292,-1.52895 -0.61665,0 -1.12348,0.29565 -1.31777,0.71801 h -0.0169 v -0.61664 h -0.76024 z" y="30.29347"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Avenir LT Std';-inkscape-font-specification:'Avenir LT Std Semi-Bold';fill:#000000;stroke-width:0.21118042" x="23.133614"
id="path956" /> id="tspan872-0"
<path sodipodi:role="line">listmonk</tspan></text>
d="m 126.56471,104.90855 h 0.76025 v -2.07802 l 1.85839,2.07802 h 1.08124 l -2.02733,-2.17939 1.86683,-1.81615 h -1.0559 l -1.72323,1.73168 v -4.12224 h -0.76025 z"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Avenir LT Std';-inkscape-font-specification:'Avenir LT Std Semi-Bold';fill:#000000;stroke-width:0.21118042"
id="path958" />
</g>
<circle <circle
style="fill:none;fill-opacity:1;stroke:#7f2aff;stroke-width:1.05596864;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" r="3.1873188"
id="path874" cy="27.647591"
cx="92.280685" cx="16.66629"
cy="102.38731" id="circle876-1"
r="3.0238743" /> style="fill:none;fill-opacity:1;stroke:#7f2aff;stroke-width:1.11304522;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
inkscape:export-filename="/home/kailash/Site/listmonk/static/logo.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96" />
<path <path
style="fill:#7f2aff;fill-opacity:1;stroke:none;stroke-width:1.15863311;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" inkscape:connector-curvature="0"
d="m 92.280686,99.698318 a 3.0238741,3.6404374 0 0 0 -3.023758,3.640282 3.0238741,3.6404374 0 0 0 0.0697,0.75725 3.0238741,3.6404374 0 0 1 2.954053,-2.87212 3.0238741,3.6404374 0 0 1 2.954051,2.88305 3.0238741,3.6404374 0 0 0 0.0697,-0.76818 3.0238741,3.6404374 0 0 0 -3.023756,-3.640282 z" id="path878-0"
id="circle878" d="m 16.666291,24.813242 a 3.1873187,3.8372081 0 0 0 -3.187196,3.837044 3.1873187,3.8372081 0 0 0 0.07347,0.79818 3.1873187,3.8372081 0 0 1 3.113724,-3.027362 3.1873187,3.8372081 0 0 1 3.113721,3.038883 3.1873187,3.8372081 0 0 0 0.07347,-0.809701 3.1873187,3.8372081 0 0 0 -3.187196,-3.837044 z"
inkscape:connector-curvature="0" /> style="fill:#7f2aff;fill-opacity:1;stroke:none;stroke-width:1.22125876;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
<path inkscape:export-filename="/home/kailash/Site/listmonk/static/logo.png"
style="fill:#7f2aff;fill-opacity:1;stroke:none;stroke-width:1.05596864;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" inkscape:export-xdpi="96"
id="path873" inkscape:export-ydpi="96" />
sodipodi:type="arc"
sodipodi:cx="92.280685"
sodipodi:cy="-99.267464"
sodipodi:rx="1.6985958"
sodipodi:ry="1.6985958"
sodipodi:start="0"
sodipodi:end="3.1415927"
d="m 93.979281,-99.267464 a 1.6985958,1.6985958 0 0 1 -0.849298,1.471027 1.6985958,1.6985958 0 0 1 -1.698596,0 1.6985958,1.6985958 0 0 1 -0.849297,-1.471027 l 1.698595,0 z"
transform="scale(1,-1)" />
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 7.9 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

File diff suppressed because it is too large Load Diff

View File

@ -1,121 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="41.535763mm"
height="8.3702965mm"
viewBox="0 0 41.535763 8.3702965"
version="1.1"
id="svg8"
sodipodi:docname="listmonk.svg"
inkscape:version="0.92.3 (2405546, 2018-03-11)">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1"
inkscape:cx="41.789813"
inkscape:cy="42.352202"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1853"
inkscape:window-height="1025"
inkscape:window-x="67"
inkscape:window-y="27"
inkscape:window-maximized="1"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-88.728827,-97.568868)">
<g
aria-label="listmonk"
style="font-style:normal;font-weight:normal;font-size:8.44721699px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.21118042"
id="text817">
<path
d="m 98.79092,104.90855 h 0.76025 v -6.3861 h -0.76025 z"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Avenir LT Std';-inkscape-font-specification:'Avenir LT Std Semi-Bold';fill:#000000;stroke-width:0.21118042"
id="path944" />
<path
d="m 100.82023,104.90855 h 0.76025 v -4.00398 h -0.76025 z m -0.17739,-5.440011 c 0,0.3041 0.25342,0.557521 0.55752,0.557521 0.3041,0 0.55751,-0.253421 0.55751,-0.557521 0,-0.3041 -0.25341,-0.557517 -0.55751,-0.557517 -0.3041,0 -0.55752,0.253417 -0.55752,0.557517 z"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Avenir LT Std';-inkscape-font-specification:'Avenir LT Std Semi-Bold';fill:#000000;stroke-width:0.21118042"
id="path946" />
<path
d="m 105.51042,101.46208 c -0.28721,-0.47304 -0.83628,-0.65888 -1.36845,-0.65888 -0.7518,0 -1.5205,0.39702 -1.5205,1.23329 0,0.7687 0.57441,0.97988 1.22485,1.14038 0.32944,0.076 0.96298,0.16049 0.96298,0.61664 0,0.34634 -0.42236,0.50684 -0.81093,0.50684 -0.43926,0 -0.72646,-0.22808 -0.97143,-0.47305 l -0.57441,0.47305 c 0.39701,0.54062 0.88695,0.70956 1.54584,0.70956 0.79403,0 1.62186,-0.35478 1.62186,-1.25863 0,-0.7518 -0.50683,-1.00522 -1.16571,-1.16572 -0.33789,-0.076 -1.02212,-0.1436 -1.02212,-0.62509 0,-0.28721 0.31255,-0.4477 0.66733,-0.4477 0.38013,0 0.64199,0.17739 0.81938,0.39701 z"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Avenir LT Std';-inkscape-font-specification:'Avenir LT Std Semi-Bold';fill:#000000;stroke-width:0.21118042"
id="path948" />
<path
d="m 108.68116,100.90457 h -1.08969 v -1.123484 h -0.76025 v 1.123484 h -0.87851 v 0.65888 h 0.87851 v 2.08646 c 0,0.64199 0.0169,1.36 1.19106,1.36 0.15205,0 0.50683,-0.0338 0.68422,-0.13515 v -0.69267 c -0.15205,0.0929 -0.36323,0.11826 -0.54062,0.11826 -0.57441,0 -0.57441,-0.47305 -0.57441,-0.92075 v -1.81615 h 1.08969 z"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Avenir LT Std';-inkscape-font-specification:'Avenir LT Std Semi-Bold';fill:#000000;stroke-width:0.21118042"
id="path950" />
<path
d="m 109.65378,104.90855 h 0.76025 v -2.07802 c 0,-0.90385 0.48994,-1.31776 1.039,-1.31776 0.73491,0 0.84473,0.54062 0.84473,1.30087 v 2.09491 h 0.76025 v -2.18783 c 0,-0.70957 0.2872,-1.20795 1.02211,-1.20795 0.73491,0 0.86162,0.55751 0.86162,1.16571 v 2.23007 h 0.76024 v -2.33144 c 0,-0.8954 -0.2872,-1.77391 -1.52049,-1.77391 -0.4815,0 -1.00522,0.25342 -1.26709,0.74335 -0.25341,-0.48993 -0.65888,-0.74335 -1.25018,-0.74335 -0.71802,0 -1.20796,0.48994 -1.28398,0.72646 h -0.0169 v -0.62509 h -0.70956 z"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Avenir LT Std';-inkscape-font-specification:'Avenir LT Std Semi-Bold';fill:#000000;stroke-width:0.21118042"
id="path952" />
<path
d="m 117.46376,102.90656 c 0,-0.81094 0.50683,-1.39379 1.31776,-1.39379 0.81094,0 1.31777,0.58285 1.31777,1.39379 0,0.81093 -0.50683,1.39379 -1.31777,1.39379 -0.81093,0 -1.31776,-0.58286 -1.31776,-1.39379 z m -0.81094,0 c 0,1.16571 0.93765,2.10335 2.1287,2.10335 1.19106,0 2.1287,-0.93764 2.1287,-2.10335 0,-1.16572 -0.93764,-2.10336 -2.1287,-2.10336 -1.19105,0 -2.1287,0.93764 -2.1287,2.10336 z"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Avenir LT Std';-inkscape-font-specification:'Avenir LT Std Semi-Bold';fill:#000000;stroke-width:0.21118042"
id="path954" />
<path
d="m 121.86265,104.90855 h 0.76024 v -2.06112 c 0,-0.9292 0.4815,-1.33466 1.11504,-1.33466 0.48149,0 0.9123,0.27875 0.9123,1.03056 v 2.36522 h 0.76025 v -2.5764 c 0,-1.06435 -0.67578,-1.52895 -1.45292,-1.52895 -0.61665,0 -1.12348,0.29565 -1.31777,0.71801 h -0.0169 v -0.61664 h -0.76024 z"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Avenir LT Std';-inkscape-font-specification:'Avenir LT Std Semi-Bold';fill:#000000;stroke-width:0.21118042"
id="path956" />
<path
d="m 126.56471,104.90855 h 0.76025 v -2.07802 l 1.85839,2.07802 h 1.08124 l -2.02733,-2.17939 1.86683,-1.81615 h -1.0559 l -1.72323,1.73168 v -4.12224 h -0.76025 z"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Avenir LT Std';-inkscape-font-specification:'Avenir LT Std Semi-Bold';fill:#000000;stroke-width:0.21118042"
id="path958" />
</g>
<circle
style="fill:none;fill-opacity:1;stroke:#7f2aff;stroke-width:1.05596864;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path874"
cx="92.280685"
cy="102.38731"
r="3.0238743" />
<path
style="fill:#7f2aff;fill-opacity:1;stroke:none;stroke-width:1.15863311;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 92.280686,99.698318 a 3.0238741,3.6404374 0 0 0 -3.023758,3.640282 3.0238741,3.6404374 0 0 0 0.0697,0.75725 3.0238741,3.6404374 0 0 1 2.954053,-2.87212 3.0238741,3.6404374 0 0 1 2.954051,2.88305 3.0238741,3.6404374 0 0 0 0.0697,-0.76818 3.0238741,3.6404374 0 0 0 -3.023756,-3.640282 z"
id="circle878"
inkscape:connector-curvature="0" />
<path
style="fill:#7f2aff;fill-opacity:1;stroke:none;stroke-width:1.05596864;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path873"
sodipodi:type="arc"
sodipodi:cx="92.280685"
sodipodi:cy="-99.267464"
sodipodi:rx="1.6985958"
sodipodi:ry="1.6985958"
sodipodi:start="0"
sodipodi:end="3.1415927"
d="m 93.979281,-99.267464 a 1.6985958,1.6985958 0 0 1 -0.849298,1.471027 1.6985958,1.6985958 0 0 1 -1.698596,0 1.6985958,1.6985958 0 0 1 -0.849297,-1.471027 l 1.698595,0 z"
transform="scale(1,-1)" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 7.9 KiB