You've already forked joplin
							
							
				mirror of
				https://github.com/laurent22/joplin.git
				synced 2025-10-31 00:07:48 +02:00 
			
		
		
		
	All: Handling of unsyncable items
This commit is contained in:
		| @@ -259,6 +259,14 @@ class Application extends BaseApplication { | ||||
| 			}, { | ||||
| 				label: _('Tools'), | ||||
| 				submenu: [{ | ||||
| 					label: _('Synchronisation status'), | ||||
| 					click: () => { | ||||
| 						this.dispatch({ | ||||
| 							type: 'NAV_GO', | ||||
| 							routeName: 'Status', | ||||
| 						}); | ||||
| 					} | ||||
| 				},{ | ||||
| 					label: _('Options'), | ||||
| 					click: () => { | ||||
| 						this.dispatch({ | ||||
|   | ||||
| @@ -338,17 +338,17 @@ class MainScreenComponent extends React.Component { | ||||
| 		const onViewDisabledItemsClick = () => { | ||||
| 			this.props.dispatch({ | ||||
| 				type: 'NAV_GO', | ||||
| 				routeName: 'SyncDisabledItems', | ||||
| 				routeName: 'Status', | ||||
| 			}); | ||||
| 		} | ||||
|  | ||||
| 		const messageComp = ( | ||||
| 		const messageComp = this.props.hasDisabledSyncItems ? ( | ||||
| 			<div style={styles.messageBox}> | ||||
| 				<span style={theme.textStyle}> | ||||
| 					{_('Some items cannot be synchronised.')} <a href="#" onClick={() => { onViewDisabledItemsClick() }}>{_('View them now')}</a> | ||||
| 				</span> | ||||
| 			</div> | ||||
| 		); | ||||
| 		) : null; | ||||
|  | ||||
| 		return ( | ||||
| 			<div style={style}> | ||||
| @@ -381,6 +381,7 @@ const mapStateToProps = (state) => { | ||||
| 		noteVisiblePanes: state.noteVisiblePanes, | ||||
| 		folders: state.folders, | ||||
| 		notes: state.notes, | ||||
| 		hasDisabledSyncItems: state.hasDisabledSyncItems, | ||||
| 	}; | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -8,7 +8,7 @@ const { Setting } = require('lib/models/setting.js'); | ||||
|  | ||||
| const { MainScreen } = require('./MainScreen.min.js'); | ||||
| const { OneDriveLoginScreen } = require('./OneDriveLoginScreen.min.js'); | ||||
| const { SyncDisabledItemsScreen } = require('./SyncDisabledItemsScreen.min.js'); | ||||
| const { StatusScreen } = require('./StatusScreen.min.js'); | ||||
| const { ImportScreen } = require('./ImportScreen.min.js'); | ||||
| const { ConfigScreen } = require('./ConfigScreen.min.js'); | ||||
| const { Navigator } = require('./Navigator.min.js'); | ||||
| @@ -76,7 +76,7 @@ class RootComponent extends React.Component { | ||||
| 			OneDriveLogin: { screen: OneDriveLoginScreen, title: () => _('OneDrive Login') }, | ||||
| 			Import: { screen: ImportScreen, title: () => _('Import') }, | ||||
| 			Config: { screen: ConfigScreen, title: () => _('Options') }, | ||||
| 			SyncDisabledItems: { screen: SyncDisabledItemsScreen, title: () => _('Items that cannot be synchronised') }, | ||||
| 			Status: { screen: StatusScreen, title: () => _('Synchronisation Status') }, | ||||
| 		}; | ||||
|  | ||||
| 		return ( | ||||
|   | ||||
							
								
								
									
										147
									
								
								ElectronClient/app/gui/StatusScreen.jsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										147
									
								
								ElectronClient/app/gui/StatusScreen.jsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,147 @@ | ||||
| const React = require('react'); | ||||
| const { connect } = require('react-redux'); | ||||
| const { reg } = require('lib/registry.js'); | ||||
| const { Setting } = require('lib/models/setting.js'); | ||||
| const { bridge } = require('electron').remote.require('./bridge'); | ||||
| const { Header } = require('./Header.min.js'); | ||||
| const { themeStyle } = require('../theme.js'); | ||||
| const { _ } = require('lib/locale.js'); | ||||
| const { ReportService } = require('lib/services/report.js'); | ||||
| const { BaseItem } = require('lib/models/base-item.js'); | ||||
|  | ||||
| class StatusScreenComponent extends React.Component { | ||||
|  | ||||
| 	constructor() { | ||||
| 		super(); | ||||
| 		this.state = { | ||||
| 			report: [], | ||||
| 			disabledItems: [], | ||||
| 		}; | ||||
| 	} | ||||
|  | ||||
| 	componentWillMount() { | ||||
| 		this.resfreshScreen(); | ||||
| 	} | ||||
|  | ||||
| 	async resfreshScreen() { | ||||
| 		const service = new ReportService(); | ||||
| 		const report = await service.status(Setting.value('sync.target')); | ||||
| 		const disabledItems = await BaseItem.syncDisabledItems(); | ||||
| 		this.setState({ | ||||
| 			report: report, | ||||
| 			disabledItems: disabledItems, | ||||
| 		}); | ||||
| 	} | ||||
|  | ||||
| 	render() { | ||||
| 		const theme = themeStyle(this.props.theme); | ||||
| 		const style = this.props.style; | ||||
|  | ||||
| 		const headerStyle = { | ||||
| 			width: style.width, | ||||
| 		}; | ||||
|  | ||||
| 		const containerPadding = 10; | ||||
|  | ||||
| 		const containerStyle = { | ||||
| 			padding: containerPadding, | ||||
| 			overflowY: 'auto', | ||||
| 			height: style.height - theme.headerHeight - containerPadding * 2, | ||||
| 		}; | ||||
|  | ||||
| 		function renderSectionTitleHtml(key, title) { | ||||
| 			return <h2 key={'section_' + key} style={theme.h2Style}>{title}</h2> | ||||
| 		} | ||||
|  | ||||
| 		function renderSectionHtml(key, section) { | ||||
| 			let itemsHtml = []; | ||||
|  | ||||
| 			itemsHtml.push(renderSectionTitleHtml(section.title, section.title)); | ||||
|  | ||||
| 			for (let n in section.body) { | ||||
| 				if (!section.body.hasOwnProperty(n)) continue; | ||||
| 				itemsHtml.push(<div style={theme.textStyle} key={'item_' + n}>{section.body[n]}</div>); | ||||
| 			} | ||||
|  | ||||
| 			return ( | ||||
| 				<div key={key}> | ||||
| 					{itemsHtml} | ||||
| 				</div> | ||||
| 			); | ||||
| 		} | ||||
|  | ||||
| 		function renderBodyHtml(report, disabledItems) { | ||||
| 			let output = []; | ||||
| 			let baseStyle = { | ||||
| 				paddingLeft: 6, | ||||
| 				paddingRight: 6, | ||||
| 				paddingTop: 2, | ||||
| 				paddingBottom: 2, | ||||
| 				flex: 0, | ||||
| 				color: theme.color, | ||||
| 				fontSize: theme.fontSize, | ||||
| 			}; | ||||
|  | ||||
| 			let sectionsHtml = []; | ||||
|  | ||||
| 			if (disabledItems.length) { | ||||
| 				const titleHtml = [renderSectionTitleHtml('disabled_sync_items', _('Items that cannot be synchronised'))]; | ||||
| 				const trsHtml = []; | ||||
| 				for (let i = 0; i < disabledItems.length; i++) { | ||||
| 					const row = disabledItems[i]; | ||||
| 					trsHtml.push(<tr key={'item_' + i}><td style={theme.textStyle}>{row.item.title}</td><td style={theme.textStyle}>{row.syncInfo.sync_disabled_reason}</td></tr>); | ||||
| 				} | ||||
|  | ||||
| 				sectionsHtml.push( | ||||
| 					<div key={'disabled_sync_items'}> | ||||
| 						{titleHtml} | ||||
| 						<table> | ||||
| 							<tbody> | ||||
| 								<tr><th style={theme.textStyle}>{_('Name')}</th><th style={theme.textStyle}>{_('Reason')}</th></tr> | ||||
| 								{trsHtml} | ||||
| 							</tbody> | ||||
| 						</table> | ||||
| 					</div> | ||||
| 				); | ||||
| 			} | ||||
|  | ||||
| 			for (let i = 0; i < report.length; i++) { | ||||
| 				let section = report[i]; | ||||
| 				if (!section.body.length) continue; | ||||
| 				sectionsHtml.push(renderSectionHtml(i, section)); | ||||
| 			} | ||||
|  | ||||
| 			return ( | ||||
| 				<div> | ||||
| 					{sectionsHtml} | ||||
| 				</div> | ||||
| 			); | ||||
| 		} | ||||
|  | ||||
| 		console.info(this.state.disabledItems); | ||||
|  | ||||
| 		let body = renderBodyHtml(this.state.report, this.state.disabledItems); | ||||
| 		 | ||||
| 		return ( | ||||
| 			<div style={style}> | ||||
| 				<Header style={headerStyle} /> | ||||
| 				<div style={containerStyle}> | ||||
| 					{body} | ||||
| 				</div> | ||||
| 			</div> | ||||
| 		); | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
| const mapStateToProps = (state) => { | ||||
| 	return { | ||||
| 		theme: state.settings.theme, | ||||
| 		settings: state.settings, | ||||
| 		locale: state.settings.locale, | ||||
| 	}; | ||||
| }; | ||||
|  | ||||
| const StatusScreen = connect(mapStateToProps)(StatusScreenComponent); | ||||
|  | ||||
| module.exports = { StatusScreen }; | ||||
| @@ -1,45 +0,0 @@ | ||||
| const React = require('react'); | ||||
| const { connect } = require('react-redux'); | ||||
| const { reg } = require('lib/registry.js'); | ||||
| const { Setting } = require('lib/models/setting.js'); | ||||
| const { bridge } = require('electron').remote.require('./bridge'); | ||||
| const { Header } = require('./Header.min.js'); | ||||
| const { themeStyle } = require('../theme.js'); | ||||
| const { _ } = require('lib/locale.js'); | ||||
|  | ||||
| class SyncDisabledItemsScreenComponent extends React.Component { | ||||
|  | ||||
| 	render() { | ||||
| 		const theme = themeStyle(this.props.theme); | ||||
| 		const style = this.props.style; | ||||
|  | ||||
| 		const headerStyle = { | ||||
| 			width: style.width, | ||||
| 		}; | ||||
|  | ||||
| 		const containerStyle = { | ||||
| 			padding: 10, | ||||
| 		}; | ||||
| 		 | ||||
| 		return ( | ||||
| 			<div style={style}> | ||||
| 				<Header style={headerStyle} /> | ||||
| 				<div style={containerStyle}> | ||||
| 				</div> | ||||
| 			</div> | ||||
| 		); | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
| const mapStateToProps = (state) => { | ||||
| 	return { | ||||
| 		theme: state.settings.theme, | ||||
| 		settings: state.settings, | ||||
| 		locale: state.settings.locale, | ||||
| 	}; | ||||
| }; | ||||
|  | ||||
| const SyncDisabledItemsScreen = connect(mapStateToProps)(SyncDisabledItemsScreenComponent); | ||||
|  | ||||
| module.exports = { SyncDisabledItemsScreen }; | ||||
| @@ -9,6 +9,19 @@ body, textarea { | ||||
| 	overflow: hidden; | ||||
| } | ||||
|  | ||||
| table { | ||||
| 	border-collapse: collapse; | ||||
| } | ||||
|  | ||||
| table th { | ||||
| 	text-align: left; | ||||
| } | ||||
|  | ||||
| table td, table th { | ||||
| 	padding: .5em; | ||||
| 	border: 1px solid #ccc; | ||||
| } | ||||
|  | ||||
| /* By default, the Ice Editor displays invalid characters, such as non-breaking spaces | ||||
|    as red boxes, but since those are actually valid characters and common in imported | ||||
|    Evernote data, we hide them here. */ | ||||
|   | ||||
| @@ -71,6 +71,9 @@ globalStyle.textStyle2 = Object.assign({}, globalStyle.textStyle, { | ||||
| 	color: globalStyle.color2, | ||||
| }); | ||||
|  | ||||
| globalStyle.h2Style = Object.assign({}, globalStyle.textStyle); | ||||
| globalStyle.h2Style.fontSize *= 1.3; | ||||
|  | ||||
| let themeCache_ = {}; | ||||
|  | ||||
| function themeStyle(theme) { | ||||
|   | ||||
| @@ -387,7 +387,8 @@ class BaseItem extends BaseModel { | ||||
| 		const rows = await this.db().selectAll('SELECT * FROM sync_items WHERE sync_disabled = 1'); | ||||
| 		let output = []; | ||||
| 		for (let i = 0; i < rows.length; i++) { | ||||
| 			const item = await this.loadItem(rows[i].item_type, rows[i].id); | ||||
| 			const item = await this.loadItem(rows[i].item_type, rows[i].item_id); | ||||
| 			if (!item) continue; // The referenced item no longer exist | ||||
| 			output.push({ | ||||
| 				syncInfo: rows[i], | ||||
| 				item: item, | ||||
|   | ||||
| @@ -25,7 +25,8 @@ const defaultState = { | ||||
| 	searchQuery: '', | ||||
| 	settings: {}, | ||||
| 	appState: 'starting', | ||||
| 	windowContentSize: { width: 0, height: 0 }, | ||||
| 	//windowContentSize: { width: 0, height: 0 }, | ||||
| 	hasDisabledSyncItems: false, | ||||
| }; | ||||
|  | ||||
| // When deleting a note, tag or folder | ||||
| @@ -395,6 +396,12 @@ const reducer = (state = defaultState, action) => { | ||||
| 				newState.appState = action.state; | ||||
| 				break; | ||||
|  | ||||
| 			case 'SYNC_HAS_DISABLED_SYNC_ITEMS': | ||||
|  | ||||
| 				newState = Object.assign({}, state); | ||||
| 				newState.hasDisabledSyncItems = true; | ||||
| 				break; | ||||
|  | ||||
| 		} | ||||
| 	} catch (error) { | ||||
| 		error.message = 'In reducer: ' + error.message + ' Action: ' + JSON.stringify(action); | ||||
|   | ||||
| @@ -253,8 +253,9 @@ class Synchronizer { | ||||
|  | ||||
| 					this.logSyncOperation(action, local, remote, reason); | ||||
|  | ||||
| 					async function handleCannotSyncItem(syncTargetId, item, cannotSyncReason) { | ||||
| 					const handleCannotSyncItem = async (syncTargetId, item, cannotSyncReason) => { | ||||
| 						await ItemClass.saveSyncDisabled(syncTargetId, item, cannotSyncReason); | ||||
| 						this.dispatch({ type: 'SYNC_HAS_DISABLED_SYNC_ITEMS' }); | ||||
| 					} | ||||
|  | ||||
| 					if (local.type_ == BaseModel.TYPE_RESOURCE && (action == 'createRemote' || (action == 'itemConflict' && remote))) { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user