UI migrated to Bootstrap 4, FontAwesome 5 and CoreUI theme.

This commit is contained in:
Tomas Bures 2018-12-28 10:57:00 +01:00
parent 41d74e3cc7
commit 64af46b685
11 changed files with 99 additions and 69 deletions

View file

@ -88,7 +88,7 @@ export default class Statistics extends Component {
const val = entity[key] const val = entity[key]
return ( return (
<AlignedRow label={label}><span className={styles.statsMetrics}>{val}</span>{showZoomIn && <span className={styles.zoomIn}><Link to={`/campaigns/${entity.id}/statistics/${key}`}><Icon icon="zoom-in"/></Link></span>}</AlignedRow> <AlignedRow label={label}><span className={styles.statsMetrics}>{val}</span>{showZoomIn && <span className={styles.zoomIn}><Link to={`/campaigns/${entity.id}/statistics/${key}`}><Icon icon="search-plus"/></Link></span>}</AlignedRow>
); );
} }
@ -103,7 +103,7 @@ export default class Statistics extends Component {
return ( return (
<AlignedRow label={label}> <AlignedRow label={label}>
{showZoomIn && <span className={styles.statsProgressBarZoomIn}><Link to={`/campaigns/${entity.id}/statistics/${key}`}><Icon icon="zoom-in"/></Link></span>} {showZoomIn && <span className={styles.statsProgressBarZoomIn}><Link to={`/campaigns/${entity.id}/statistics/${key}`}><Icon icon="search-plus"/></Link></span>}
<div className={`progress ${styles.statsProgressBar}`}> <div className={`progress ${styles.statsProgressBar}`}>
<div <div
className={`progress-bar progress-bar-${progressBarClass}`} className={`progress-bar progress-bar-${progressBarClass}`}

View file

@ -86,7 +86,6 @@
} }
.sectionTitle { .sectionTitle {
font-weight: bold;
margin-bottom: 30px; margin-bottom: 30px;
} }

View file

@ -173,8 +173,13 @@ export default class Files extends Component {
{ {
this.props.entity.permissions.includes(this.props.managePermission) && this.props.entity.permissions.includes(this.props.managePermission) &&
<Dropzone onDrop={::this.onDrop} className={styles.dropZone} activeClassName={styles.dropZoneActive}> <Dropzone onDrop={::this.onDrop}>
{state => state.isDragActive ? t('dropCountFile', {count: state.draggedFiles.length}) : t('dropFilesHere')} {({getRootProps, getInputProps, isDragActive, draggedFiles}) => (
<div {...getRootProps()} className={styles.dropZone + (isDragActive ? ' ' + styles.dropZoneActive : '')}>
<input {...getInputProps()} />
<p>{isDragActive ? t('dropCountFile', {count: draggedFiles.length}) : t('dropFilesHere')}</p>
</div>
)}
</Dropzone> </Dropzone>
} }

View file

@ -32,16 +32,20 @@ $editorNormalHeight: 800px !default;
background: #f86c6b; background: #f86c6b;
width: 100%; width: 100%;
height: $navbarHeight; height: $navbarHeight;
display: flex;
justify-content: space-between;
} }
.navbarLeft {
.logo { .logo {
float: left; display: inline-block;
height: $navbarHeight; height: $navbarHeight;
padding: 5px 0 5px 10px; padding: 5px 0 5px 10px;
filter: brightness(0) invert(1); filter: brightness(0) invert(1);
} }
.title { .title {
display: inline-block;
padding: 5px 0 5px 10px; padding: 5px 0 5px 10px;
font-size: 18px; font-size: 18px;
font-weight: bold; font-weight: bold;
@ -49,10 +53,11 @@ $editorNormalHeight: 800px !default;
color: white; color: white;
height: $navbarHeight; height: $navbarHeight;
} }
}
.navbarRight {
.btn, .btnDisabled { .btn, .btnDisabled {
display: block; display: inline-block;
float: right;
padding: 0px 15px; padding: 0px 15px;
line-height: $navbarHeight; line-height: $navbarHeight;
text-align: center; text-align: center;
@ -82,3 +87,4 @@ $editorNormalHeight: 800px !default;
color: #621d1d; color: #621d1d;
} }
} }
}

View file

@ -94,11 +94,15 @@ export class CKEditorHost extends Component {
return ( return (
<div className={this.state.fullscreen ? styles.editorFullscreen : styles.editor}> <div className={this.state.fullscreen ? styles.editorFullscreen : styles.editor}>
<div className={styles.navbar}> <div className={styles.navbar}>
<div className={styles.navbarLeft}>
{this.state.fullscreen && <img className={styles.logo} src={getTrustedUrl('static/mailtrain-notext.png')}/>} {this.state.fullscreen && <img className={styles.logo} src={getTrustedUrl('static/mailtrain-notext.png')}/>}
<div className={styles.title}>{this.props.title}</div> <div className={styles.title}>{this.props.title}</div>
<a className={styles.btn} onClick={::this.toggleFullscreenAsync}><Icon icon="window-maximize"/></a> </div>
<a className={styles.btn} onClick={this.props.onTestSend}><Icon icon="send"/></a> <div className={styles.navbarRight}>
{this.props.canSave ? <a className={styles.btn} onClick={this.props.onSave}><Icon icon="floppy-disk"/></a> : <span className={styles.btnDisabled}><Icon icon="floppy-disk"/></span>} {this.props.canSave ? <a className={styles.btn} onClick={this.props.onSave} title={t('Save')}><Icon icon="save"/></a> : <span className={styles.btnDisabled}><Icon icon="save"/></span>}
<a className={styles.btn} onClick={this.props.onTestSend} title={t('Send test e-mail')}><Icon icon="at"/></a>
<a className={styles.btn} onClick={::this.toggleFullscreenAsync} title={t('Maximize editor')}><Icon icon="window-maximize"/></a>
</div>
</div> </div>
<UntrustedContentHost ref={node => this.contentNode = node} className={styles.host} singleToken={true} contentProps={editorData} contentSrc="ckeditor/editor" tokenMethod="ckeditor" tokenParams={editorData}/> <UntrustedContentHost ref={node => this.contentNode = node} className={styles.host} singleToken={true} contentProps={editorData} contentSrc="ckeditor/editor" tokenMethod="ckeditor" tokenParams={editorData}/>
</div> </div>

View file

@ -88,13 +88,17 @@ export class CodeEditorHost extends Component {
return ( return (
<div className={this.state.fullscreen ? styles.editorFullscreen : styles.editor}> <div className={this.state.fullscreen ? styles.editorFullscreen : styles.editor}>
<div className={styles.navbar}> <div className={styles.navbar}>
<div className={styles.navbarLeft}>
{this.state.fullscreen && <img className={styles.logo} src={getTrustedUrl('static/mailtrain-notext.png')}/>} {this.state.fullscreen && <img className={styles.logo} src={getTrustedUrl('static/mailtrain-notext.png')}/>}
<div className={styles.title}>{this.props.title}</div> <div className={styles.title}>{this.props.title}</div>
<a className={styles.btn} onClick={::this.toggleFullscreenAsync}><Icon icon="window-maximize"/></a> </div>
<a className={styles.btn} onClick={this.props.onTestSend}><Icon icon="send"/></a> <div className={styles.navbarRight}>
<a className={styles.btn} onClick={::this.togglePreviewAsync}><Icon icon={this.state.preview ? 'eye-close': 'eye-open'}/></a> <a className={styles.btn} onClick={::this.toggleWrapAsync} title={this.state.wrap ? t('Disable word wrap') : t('Enable word wrap')}>{this.state.wrap ? 'WRAP': 'NOWRAP'}</a>
{this.props.canSave ? <a className={styles.btn} onClick={this.props.onSave}><Icon icon="floppy-disk"/></a> : <span className={styles.btnDisabled}><Icon icon="floppy-disk"/></span>} {this.props.canSave ? <a className={styles.btn} onClick={this.props.onSave} title={t('Save')}><Icon icon="save"/></a> : <span className={styles.btnDisabled}><Icon icon="floppy-disk"/></span>}
<a className={styles.btn} onClick={::this.toggleWrapAsync}>{this.state.wrap ? 'WRAP': 'NOWRAP'}</a> <a className={styles.btn} onClick={this.props.onTestSend} title={t('Send test e-mail')}><Icon icon="at"/></a>
<a className={styles.btn} onClick={::this.togglePreviewAsync} title={this.state.preview ? t('Hide preview'): t('Show preview')}><Icon icon={this.state.preview ? 'eye-slash': 'eye'}/></a>
<a className={styles.btn} onClick={::this.toggleFullscreenAsync} title={t('Maximize editor')}><Icon icon="window-maximize"/></a>
</div>
</div> </div>
<UntrustedContentHost ref={node => this.contentNode = node} className={styles.host} singleToken={true} contentProps={editorData} contentSrc="codeeditor/editor" tokenMethod="codeeditor" tokenParams={tokenData}/> <UntrustedContentHost ref={node => this.contentNode = node} className={styles.host} singleToken={true} contentProps={editorData} contentSrc="codeeditor/editor" tokenMethod="codeeditor" tokenParams={tokenData}/>
</div> </div>

View file

@ -68,11 +68,15 @@ export class GrapesJSHost extends Component {
return ( return (
<div className={this.state.fullscreen ? styles.editorFullscreen : styles.editor}> <div className={this.state.fullscreen ? styles.editorFullscreen : styles.editor}>
<div className={styles.navbar}> <div className={styles.navbar}>
<div className={styles.navbarLeft}>
{this.state.fullscreen && <img className={styles.logo} src={getTrustedUrl('static/mailtrain-notext.png')}/>} {this.state.fullscreen && <img className={styles.logo} src={getTrustedUrl('static/mailtrain-notext.png')}/>}
<div className={styles.title}>{this.props.title}</div> <div className={styles.title}>{this.props.title}</div>
<a className={styles.btn} onClick={::this.toggleFullscreenAsync}><Icon icon="window-maximize"/></a> </div>
<a className={styles.btn} onClick={this.props.onTestSend}><Icon icon="send"/></a> <div className={styles.navbarRight}>
{this.props.canSave ? <a className={styles.btn} onClick={this.props.onSave}><Icon icon="floppy-disk"/></a> : <span className={styles.btnDisabled}><Icon icon="floppy-disk"/></span>} {this.props.canSave ? <a className={styles.btn} onClick={this.props.onSave} title={t('Save')}><Icon icon="save"/></a> : <span className={styles.btnDisabled}><Icon icon="save"/></span>}
<a className={styles.btn} onClick={this.props.onTestSend} title={t('Send test e-mail')}><Icon icon="at"/></a>
<a className={styles.btn} onClick={::this.toggleFullscreenAsync} title={t('Maximize editor')}><Icon icon="window-maximize"/></a>
</div>
</div> </div>
<UntrustedContentHost ref={node => this.contentNode = node} className={styles.host} singleToken={true} contentProps={editorData} contentSrc="grapesjs/editor" tokenMethod="grapesjs" tokenParams={tokenData}/> <UntrustedContentHost ref={node => this.contentNode = node} className={styles.host} singleToken={true} contentProps={editorData} contentSrc="grapesjs/editor" tokenMethod="grapesjs" tokenParams={tokenData}/>
</div> </div>

View file

@ -71,11 +71,15 @@ export class MosaicoHost extends Component {
return ( return (
<div className={this.state.fullscreen ? styles.editorFullscreen : styles.editor}> <div className={this.state.fullscreen ? styles.editorFullscreen : styles.editor}>
<div className={styles.navbar}> <div className={styles.navbar}>
<div className={styles.navbarLeft}>
{this.state.fullscreen && <img className={styles.logo} src={getTrustedUrl('static/mailtrain-notext.png')}/>} {this.state.fullscreen && <img className={styles.logo} src={getTrustedUrl('static/mailtrain-notext.png')}/>}
<div className={styles.title}>{this.props.title}</div> <div className={styles.title}>{this.props.title}</div>
<a className={styles.btn} onClick={::this.toggleFullscreenAsync}><Icon icon="window-maximize"/></a> </div>
<a className={styles.btn} onClick={this.props.onTestSend}><Icon icon="send"/></a> <div className={styles.navbarRight}>
{this.props.canSave ? <a className={styles.btn} onClick={this.props.onSave}><Icon icon="floppy-disk"/></a> : <span className={styles.btnDisabled}><Icon icon="floppy-disk"/></span>} {this.props.canSave ? <a className={styles.btn} onClick={this.props.onSave} title={t('Save')}><Icon icon="save"/></a> : <span className={styles.btnDisabled}><Icon icon="save"/></span>}
<a className={styles.btn} onClick={this.props.onTestSend} title={t('Send test e-mail')}><Icon icon="at"/></a>
<a className={styles.btn} onClick={::this.toggleFullscreenAsync} title={t('Maximize editor')}><Icon icon="window-maximize"/></a>
</div>
</div> </div>
<UntrustedContentHost ref={node => this.contentNode = node} className={styles.host} singleToken={true} contentProps={editorData} contentSrc="mosaico/editor" tokenMethod="mosaico" tokenParams={tokenData}/> <UntrustedContentHost ref={node => this.contentNode = node} className={styles.host} singleToken={true} contentProps={editorData} contentSrc="mosaico/editor" tokenMethod="mosaico" tokenParams={tokenData}/>
</div> </div>

View file

@ -123,6 +123,10 @@
text-align: center; text-align: center;
font-size: 20px; font-size: 20px;
color: #808080; color: #808080;
p:last-child {
margin-bottom: 0px;
}
} }
.dropZoneActive{ .dropZoneActive{

View file

@ -51,7 +51,7 @@ export default class List extends Component {
const columns = [ const columns = [
{ data: 4, title: "#" }, { data: 4, title: "#" },
{ data: 1, title: t('name'), { data: 1, title: t('name'),
render: (data, cmd, rowData) => rowData[2] === 'option' ? <span><Icon icon="record"/> {data}</span> : data render: (data, cmd, rowData) => rowData[2] === 'option' ? <span><Icon icon="dot-circle"/> {data}</span> : data
}, },
{ data: 2, title: t('type'), render: data => this.fieldTypes[data].label, sortable: false, searchable: false }, { data: 2, title: t('type'), render: data => this.fieldTypes[data].label, sortable: false, searchable: false },
{ data: 3, title: t('mergeTag') }, { data: 3, title: t('mergeTag') },

View file

@ -88,7 +88,7 @@ fieldTypes.gpg = {
fieldTypes.json = { fieldTypes.json = {
validate: field => {}, validate: field => {},
addColumn: (table, name) => table.json(name), addColumn: (table, name) => table.text(name),
indexed: false, indexed: false,
grouped: false, grouped: false,
enumerated: false, enumerated: false,