Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion iceberg.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* Plugin Name: Iceberg Editor
* Plugin URI: https://useiceberg.com/
* Description: Iceberg is a beautiful, flexible markdown editor for writing within the WordPress block editor. Iceberg leverages the best of WordPress, and the best of the new block editor, while getting out of your way – allowing you to focus on publishing your next post.
* Version: 1.0.0
* Version: 1.1.0
* Author: Iceberg
* Author URI: https://useiceberg.com/
* Text Domain: iceberg
Expand Down
59 changes: 59 additions & 0 deletions src/components/theme-import-export/file.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/**
* Downloads a file.
*
* @param {string} fileName File Name.
* @param {string} content File Content.
* @param {string} contentType File mime type.
*/
export function download( fileName, content, contentType ) {
const file = new window.Blob( [ content ], { type: contentType } );

// IE11 can't use the click to download technique
// we use a specific IE11 technique instead.
if ( window.navigator.msSaveOrOpenBlob ) {
window.navigator.msSaveOrOpenBlob( file, fileName );
} else {
const a = document.createElement( 'a' );
a.href = URL.createObjectURL( file );
a.download = fileName;

a.style.display = 'none';
document.body.appendChild( a );
a.click();
document.body.removeChild( a );
}
}

/**
* Reads the textual content of the given file.
*
* @param {File} file File.
* @return {Promise<string>} Content of the file.
*/
export function readTextFile( file ) {
const reader = new window.FileReader();
return new Promise( ( resolve ) => {
reader.onload = function() {
resolve( reader.result );
};
reader.readAsText( file );
} );
}

/**
* Import a reusable block from a JSON file.
*
* @param {File} file File.
* @return {Promise} Promise returning the imported reusable block.
*/
export async function importThemeSettings( file ) {
const fileContent = await readTextFile( file );
let parsedContent;
try {
parsedContent = JSON.parse( fileContent );
} catch ( e ) {
throw new Error( 'Invalid JSON file' );
}

return parsedContent;
}
149 changes: 149 additions & 0 deletions src/components/theme-import-export/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
/**
* Internal dependencies
*/
import { download, importThemeSettings } from './file';
import icons from '../icons';

/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
import { Fragment, Component } from '@wordpress/element';
import { withDispatch, withSelect } from '@wordpress/data';
import { compose, withInstanceId } from '@wordpress/compose';
import {
BaseControl,
MenuGroup,
MenuItem,
DropZoneProvider,
DropZone,
withSpokenMessages,
Button,
} from '@wordpress/components';

class ThemeImportExport extends Component {
constructor() {
super( ...arguments );

this.exportAsJSON = this.exportAsJSON.bind( this );
this.onFilesUpload = this.onFilesUpload.bind( this );
this.state = {
isImported: false,
};
}

exportAsJSON() {
const { themeSettings } = this.props;

//do export magic
const fileContent = JSON.stringify( themeSettings, null, 2 );

const fileName = 'iceberg-theme-settings.json';
download( fileName, fileContent, 'application/json' );
}

onFilesUpload( files ) {
const { updateThemeSettings, loadConfig, updateState } = this.props;
let file = files[ 0 ];

if ( files.target ) {
file = event.target.files[ 0 ];
}

if ( ! file ) {
return;
}

importThemeSettings( file )
.then( ( importedSettings ) => {
updateState( 'themeSettings', importedSettings );
updateState( 'theme', importedSettings.theme );
updateThemeSettings( importedSettings );
this.setState( { isImported: true } );

// reload variables
loadConfig( importedSettings.theme, importedSettings );
} )
.catch( () => {
this.setState( { error: true } );
} );
}

render() {
const { onToggle, onClose } = this.props;

return (
<Fragment>
<div className="components-iceberg-theme-switcher__import-export">
<BaseControl>
{ __( 'Export theme settings', 'iceberg' ) }
</BaseControl>
<Button
isSecondary
onClick={ () => {
this.exportAsJSON();
} }
>
{ __( 'Export', 'iceberg' ) }
</Button>

<BaseControl>{ __( 'Import', 'iceberg' ) }</BaseControl>
<DropZoneProvider>
<div>
{ __(
'Drag and drop iceberg-theme-settings.json file in here.',
'iceberg'
) }
<DropZone
onFilesDrop={ this.onFilesUpload }
onHTMLDrop={ this.onFilesUpload }
onDrop={ this.onFilesUpload }
/>
</div>
</DropZoneProvider>
</div>
<MenuGroup>
<MenuItem
className="components-iceberg-theme-switcher__back"
onClick={ () => {
onClose();
onToggle();
onToggle();

// focus manually to fix closing outside bug
document
.querySelector(
'.components-iceberg-theme-switcher__content .components-popover__content'
)
.focus();
} }
>
{ __( 'Back to editor themes', 'iceberg' ) }
{ icons.back }
</MenuItem>
</MenuGroup>
</Fragment>
);
}
}

export default compose( [
withInstanceId,
withSelect( ( select ) => {
const { getThemeSettings } = select( 'iceberg-settings' );

return {
themeSettings: getThemeSettings(),
};
} ),
withDispatch( ( dispatch ) => {
const { setThemeSettings } = dispatch( 'iceberg-settings' );

return {
updateThemeSettings( settings ) {
setThemeSettings( settings );
},
};
} ),
withSpokenMessages,
] )( ThemeImportExport );
3 changes: 3 additions & 0 deletions src/components/theme-import-export/style.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.components-iceberg-theme-switcher__import-export {
padding: 12px;
}
49 changes: 46 additions & 3 deletions src/components/theme-switcher/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { map, merge, assign, get } from 'lodash';
import defaults from '../theme-editor/default';
import EditorThemes from '../theme-editor/editor-themes';
import ThemeEditor from '../theme-editor';
import ThemeImportExport from '../theme-import-export';
import icons from '../icons';
import { assignVariables } from './variables';
import difference from './utils/difference';
Expand Down Expand Up @@ -47,6 +48,7 @@ class ThemeSwitcher extends Component {
isEditorThemeLoaded: false,
isEditingTheme: false,
isEditingTypography: false,
isImportExport: false,
};
}

Expand Down Expand Up @@ -162,7 +164,10 @@ class ThemeSwitcher extends Component {
}
}

this.setState( { isEditingTypography: false } );
this.setState( {
isEditingTypography: false,
isImportExport: false,
} );
updateThemeSettings( this.state.themeSettings );
};

Expand Down Expand Up @@ -269,7 +274,8 @@ class ThemeSwitcher extends Component {
renderContent={ ( { onToggle } ) => (
<Fragment>
{ ! this.state.isEditingTheme &&
! this.state.isEditingTypography ? (
! this.state.isEditingTypography &&
! this.state.isImportExport ? (
<Fragment>
<MenuGroup>
{ map(
Expand Down Expand Up @@ -358,9 +364,30 @@ class ThemeSwitcher extends Component {
) }
{ icons.typography }
</MenuItem>
<MenuItem
className="components-iceberg-theme-switcher__export"
onClick={ () => {
this.setState( {
isEditingTheme: false,
isEditingTypography: false,
isImportExport: true,
} );
this.onEditTheme(
onToggle,
'isImportExport'
);
} }
>
{ __(
'Import / Export',
'iceberg'
) }
</MenuItem>
</MenuGroup>
</Fragment>
) : (
) : null }
{ ! this.state.isEditingTheme &&
! this.state.isEditingTypography ? null : (
<ThemeEditor
onToggle={ onToggle }
loadConfig={ this.loadConfig }
Expand All @@ -383,6 +410,22 @@ class ThemeSwitcher extends Component {
} }
/>
) }

{ this.state.isImportExport && (
<ThemeImportExport
loadConfig={ this.loadConfig }
updateState={ this.updateState }
onToggle={ onToggle }
onClose={ () => {
this.setState( {
isEditingTheme: false,
isEditingTypography: false,
isImportExport: false,
} );
this.onExitEditTheme( onToggle );
} }
/>
) }
</Fragment>
) }
/>
Expand Down
1 change: 1 addition & 0 deletions src/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ $imageWidth: 230px;
@import "./components/document-info/style.scss";
@import "./components/settings/style.scss";
@import "./components/block-indicator/style.scss";
@import "./components/theme-import-export/style.scss";
@import "./components/contextual-toolbar/style.scss";

//Editor styling
Expand Down