Skip to content

Commit

Permalink
Merge branch 'release/0.7.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
Matthew Mulholland committed Dec 6, 2017
2 parents a69d758 + 7afc802 commit babac3e
Show file tree
Hide file tree
Showing 35 changed files with 572 additions and 347 deletions.
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,14 @@ Open data is more likely to be used if data consumers can:
- access the data in an open machine-readable format
- know how the data is licensed and how it can be reused

## Planned features
## Features

Using Data Curator open data producers can:

- create new tabular data from scratch or from a template
- create and edit tabular data from scratch or from a template
- open data from a CSV or Microsoft Excel file
- open multiple related data tables from a [Data Package](http://frictionlessdata.io/data-packages/)
- automatically correct common problems found in CSV and Excel files
- edit data

Using data from any of these sources, you can:

Expand All @@ -43,7 +42,7 @@ Using data from any of these sources, you can:
The schema enables you to:

- validate the whole table at once
- validate a column at a time
- validate a column at a time (planned)

Once the data is described and validated, you can share the data and its description by exporting a [Data Package](http://frictionlessdata.io/data-packages/) to:

Expand Down Expand Up @@ -194,7 +193,8 @@ To automate deployment, we are using:
- [Appveyor](https://www.appveyor.com) for Windows deployment
- [Travis](https://travis-ci.org) for macOS and Linux

`instructions to build and release on the master branch will go here`
To trigger the automated build and draft release, create and push a git tag, following the versioning pattern used in current releases.
Ensure that any changes in this tag are also released back to develop and master branches.

Changes are recorded in the [Change Log][changelog].

Expand Down
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "DataCurator",
"version": "0.6.0",
"version": "0.7.0",
"author": " <[email protected]>",
"description": "Data Curator is a simple desktop CSV editor to help describe, validate and share usable open data",
"license": "MIT",
Expand Down Expand Up @@ -83,7 +83,6 @@
"escape-regexp": "^0.0.1",
"etl": "^0.5.8",
"exports-loader": "^0.6.4",
"font-awesome": "^4.7.0",
"handsontable": "^0.34.5",
"imports-loader": "^0.7.1",
"jquery": "^3.2.1",
Expand Down
2 changes: 1 addition & 1 deletion src/main/file.js
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ function readFile(filename, format) {

// TODO: consider toggle global var and use with debounce to check when last dialog triggered so don't get too many dialogs for multiple file opens
function showAlreadyOpenedFileDialog() {
console.log('showing dialog...')
// console.log('showing dialog...')
Dialog.showMessageBox(BrowserWindow.getFocusedWindow(), {
type: 'warning',
// title is not displayed on screen on macOS
Expand Down
4 changes: 3 additions & 1 deletion src/main/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ export function createWindow() {

function closeWindowNoPrompt(result) {
let browserWindow = BrowserWindow.getAllWindows()[0]
browserWindow.destroy()
if (browserWindow) {
browserWindow.destroy()
}
}

export function createWindowTab() {
Expand Down
90 changes: 40 additions & 50 deletions src/renderer/components/Home.vue
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
</nav>
<div id="main-panel" class="panel panel-default" :class="sideNavPropertiesForMain">
<!-- <div id="main-top-panel" class="panel panel-heading"></div> -->
<div id="main-middle-panel" class="panel panel-body">
<div id="main-middle-panel" class="panel panel-body" :class="messageStatus">
<div id='csvEditor'>
<ul class="nav nav-tabs">
<li>
Expand All @@ -83,7 +83,7 @@
</div>
</div>
</div>
<div id="main-bottom-panel" class="panel-footer">
<div id="main-bottom-panel" class="panel-footer" :class="mainBottomPanelStatus">
<div id="message-panel" class="panel-default">
<!-- tidy up messages view with components -->
<div v-show="messages">
Expand All @@ -97,7 +97,9 @@
<h3>{{messagesTitle}}</h3>
<template v-if="messagesType === 'error'">
<div v-for="errorMessage in messages">
<span v-show="errorMessage.rowNumber">row no.{{errorMessage.rowNumber}}: </span><span>{{errorMessage.message}}</span>
<span v-show="errorMessage.rowNumber">(row:{{errorMessage.rowNumber}})</span>
<span v-show="errorMessage.columnNumber">(column:{{errorMessage.columnNumber}})</span>
<span>{{errorMessage.message}}</span>
</div>
</template>
<div v-else>
Expand Down Expand Up @@ -163,7 +165,7 @@ import 'bootstrap/dist/js/bootstrap.min.js'
import 'lodash/lodash.min.js'
import '../menu.js'
import {unzipFile} from '@/importPackage.js'
import {toggleHeaderOff, toggleHeaderOn} from '@/headerRow.js'
import {toggleHeaderWithFeedback} from '@/headerRow.js'
import {onNextHotIdFromTabRx, hotIdFromTab$} from '@/rxSubject.js'
import {getHotIdFromTabIdFunction} from '@/store/modules/hots.js'
export default {
Expand Down Expand Up @@ -254,7 +256,12 @@ export default {
{
label: 'encoding',
value: 'utf-8'
}]
}],
defaultPackageProperties: [{
label: 'profile',
value: 'tabular-data-package'
}],
reportSiblingClasses: ['main-bottom-panel', 'main-middle-panel']
}
},
computed: {
Expand All @@ -275,6 +282,12 @@ export default {
},
maxColAllowed() {
return getColumnCount() - 1
},
messageStatus() {
return this.messages ? 'messages-opened' : 'messages-closed'
},
mainBottomPanelStatus() {
return `${this.messageStatus} ${this.sideNavPropertiesForMain}`
}
},
methods: {
Expand All @@ -295,41 +308,27 @@ export default {
'resetTablePropertiesToObject',
'resetColumnPropertiesToObject',
'pushAllColumnsProperty',
'pushTableProperty'
'pushTableProperty',
'pushPackageProperty'
]),
closeMessages: function() {
for (let el of ['main-bottom-panel', 'main-middle-panel']) {
document.getElementById(el).classList.remove('opened')
}
this.messages = false
this.messagesType = ''
this.messageTitle = ''
},
selectionListener: function() {
this.updateActiveColumn()
this.resetSideNavArrows()
},
inferColumnProperties: async function() {
try {
let feedback = await guessColumnProperties()
this.messages = feedback
this.messages = await guessColumnProperties()
this.messagesType = 'feedback'
this.messagesTitle = 'Guess column properties'
this.reportFeedback()
} catch (err) {
console.log(err)
}
},
// TODO: tidy up error view handling and consistency in dependent usages
openMessagesOnIds: function(ids) {
for (let el of ids) {
document.getElementById(el).classList += ' opened'
}
},
closeMessagesOnIds: function(ids) {
for (let el of ids) {
document.getElementById(el).classList.remove('opened')
}
closeMessages: function() {
this.messages = false
this.messagesType = ''
this.messageTitle = ''
},
// TODO: tidy up message objects
reportValidationRowErrors: function(errorCollection) {
Expand All @@ -342,14 +341,6 @@ export default {
this.messages = 'No validation errors reported.'
this.messagesType = 'feedback'
}
this.reportFeedback()
},
reportFeedback: function() {
// console.log('updating feedback...')
let ids = ['main-bottom-panel', 'main-middle-panel']
let cssUpdateFunction = this.messages
? this.openMessagesOnIds(ids)
: this.closeMessagesOnIds(ids)
},
validateTable: async function() {
try {
Expand All @@ -369,19 +360,16 @@ export default {
this.messagesTitle = message ? 'Import Data Package Error' : 'Import Data Package Success'
this.messages = message || 'All Properties have been imported.'
this.messagesType = 'feedback'
this.reportFeedback()
},
exportPackageFeedback: function() {
this.messagesTitle = 'Export package success'
this.messages = 'Data package created.'
this.messagesType = 'feedback'
this.reportFeedback()
},
exportPackageErrors: function(errorMessages) {
this.messagesTitle = 'Export package error'
this.messages = errorMessages
this.messagesType = 'error'
this.reportFeedback()
},
createPackage: async function() {
try {
Expand Down Expand Up @@ -475,6 +463,11 @@ export default {
this.pushTableProperty({hotId: hotId, key: x.label, value: x.value})
})
},
pushDefaultPackageProperties: function() {
this.defaultPackageProperties.forEach(x => {
this.pushPackageProperty({key: x.label, value: x.value})
})
},
closeTab: async function(event) {
// do not allow single tab to be closed
if (this.tabs.length > 1) {
Expand All @@ -498,6 +491,7 @@ export default {
closeSideNav: function() {
this.enableTransition = false
this.sideNavStatus = 'closed'
this.sideNavView = ''
},
openSideNav: function() {
this.sideNavStatus = 'open'
Expand Down Expand Up @@ -575,7 +569,7 @@ export default {
},
updateToolbarMenuForButton: function(index) {
this.toolbarIndex = index
this.closeSideNav()
// this.closeSideNav()
switch (this.toolbarMenus[index].name) {
case 'Validate':
this.validateTable()
Expand Down Expand Up @@ -628,7 +622,7 @@ export default {
this.sideNavView = properties.sideNavView
this.sideNavViewTitle = properties.name || properties.sideNavView
this.enableTransition = properties.enableTransition || false
this.sideNavStatus = 'open'
this.openSideNav()
},
triggerMenuButton: function(menuName) {
let index = _.findIndex(this.toolbarMenus, function(o) {
Expand All @@ -649,14 +643,9 @@ export default {
form.style.height = this.sideNavFormHeight
}
},
toggleHeaderWithFeedback: function(hot) {
this.messages = false
if (hot.hasColHeaders()) {
toggleHeaderOff(hot)
} else {
toggleHeaderOn(hot, this.toggleHeaderErrorMessage)
}
this.reportFeedback()
toggleHeader: function() {
let hot = HotRegister.getActiveInstance()
toggleHeaderWithFeedback(hot, this.toggleHeaderErrorMessage, this.closeMessages)
},
toggleHeaderErrorMessage: function() {
this.messagesTitle = 'Header Error'
Expand Down Expand Up @@ -688,10 +677,9 @@ export default {
ipc.on('triggerMenuButton', function(event, arg) {
vueTriggerMenuButton(arg)
})
const vueToggleHeader = this.toggleHeaderWithFeedback
const vueToggleHeader = this.toggleHeader
ipc.on('toggleActiveHeaderRow', function() {
let hot = HotRegister.getActiveInstance()
vueToggleHeader(hot)
vueToggleHeader()
})
const vueAddTabWithData = this.addTabWithData
ipc.on('addTabWithData', function(e, data) {
Expand Down Expand Up @@ -747,6 +735,7 @@ export default {
onNextHotIdFromTabRx(getHotIdFromTabIdFunction())
},
created: function() {
console.log('home vue created.')
const vueGuessProperties = this.inferColumnProperties
ipc.on('guessColumnProperties', function(event, arg) {
vueGuessProperties()
Expand All @@ -759,6 +748,7 @@ export default {
ipc.on('validateTable', function(event, arg) {
vueValidateTable()
})
this.pushDefaultPackageProperties()
},
updated: function() {
if (this.loadingDataMessage && this.loadingDataMessage.length > 0) {
Expand Down
4 changes: 2 additions & 2 deletions src/renderer/components/KeyboardHelp.vue
Original file line number Diff line number Diff line change
Expand Up @@ -281,9 +281,9 @@
<td><kbd>Command &#8984;</kbd> <kbd>Z</kbd></td>
</tr>
<tr>
<td><b>Redo</b> - repeat the last data entry or edit command</td>
<td><b>Redo</b> - Undo the last Undo command</td>
<td><kbd>Ctrl</kbd> <kbd>Y</kbd></td>
<td><kbd>Command &#8984;</kbd> <kbd>Y</kbd></td>
<td><kbd>Shift &#8679;</kbd> <kbd>Command &#8984;</kbd> <kbd>Z</kbd></td>
</tr>
<tr>
<td><b>Cut</b> - move the selected data to the clipboard</td>
Expand Down
4 changes: 2 additions & 2 deletions src/renderer/data-actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import tabStore from '../renderer/store/modules/tabs.js'
import fs from 'fs'
import {fixRaggedRows} from '@/ragged-rows.js'
import {includeHeadersInData} from '@/frictionlessUtilities.js'
import {toggleHeaderOn} from '@/headerRow.js'
import {toggleHeaderNoFeedback} from '@/headerRow.js'
// import parse from 'csv-parse/lib/sync'
// import stringify from 'csv-stringify'
const $ = global.jQuery = require('jquery/dist/jquery.js')
Expand All @@ -20,7 +20,7 @@ export function loadDataIntoHot(hot, data, format) {
hot.loadData(arrays)
hot.render()
// frictionless csv header default = true
toggleHeaderOn(hot)
toggleHeaderNoFeedback(hot)
}

export function saveDataToFile(hot, format, filename, callback) {
Expand Down
6 changes: 4 additions & 2 deletions src/renderer/frictionless.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,14 @@ function checkRow(rowNumber, row, schema, errorCollector) {
for (const error of err.errors) {
// console.log('got next error')
console.log(error)
errorCollector.push({rowNumber: rowNumber, message: error.message, name: error.name})
let columnNumber = error.columnNumber || 'N/A'
errorCollector.push({columnNumber: columnNumber, rowNumber: rowNumber, message: error.message, name: error.name})
}
} else {
// console.log('got next error')
console.log(err)
errorCollector.push({rowNumber: rowNumber, message: err.message, name: err.name})
let columnNumber = err.columnNumber || 'N/A'
errorCollector.push({columnNumber: columnNumber, rowNumber: rowNumber, message: err.message, name: err.name})
}
}
}
Expand Down
13 changes: 9 additions & 4 deletions src/renderer/frictionlessDataPackage.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {createZipFile} from '@/exportPackage.js'
import {hasAllColumnNames} from '@/frictionlessUtilities.js'

export async function createDataPackage() {
let errorMessages = []
const errorMessages = []
if (!haveAllTabsGotFilenames()) {
errorMessages.push('All tabs must be saved before exporting.')
}
Expand Down Expand Up @@ -57,8 +57,14 @@ function hasAllPackageRequirements(requiredMessages) {
if (!hotStore.state.provenanceProperties || !hotStore.state.provenanceProperties.markdown) {
requiredMessages.push(`Provenance properties must be set.`)
}
if (!hotStore.state.packageProperties || _.isEmpty(hotStore.state.packageProperties)) {
let packageProperties = hotStore.state.packageProperties
if (!packageProperties || _.isEmpty(packageProperties)) {
requiredMessages.push(`Package properties must be set.`)
} else {
let name = packageProperties.name
if (!name || name.trim() === '') {
requiredMessages.push(`Package property, 'name' must be set.`)
}
}
return requiredMessages.length === 0
}
Expand All @@ -75,7 +81,7 @@ function addPackageProperties(dataPackage) {
}

async function buildAllResourcesForDataPackage(dataPackage, errorMessages) {
let resourcePaths = []
const resourcePaths = []
for (let hotId in hotStore.state.hotTabs) {
try {
let resource = await createValidResource(hotId, errorMessages)
Expand Down Expand Up @@ -132,7 +138,6 @@ function hasAllResourceRequirements(hot, requiredMessages) {
requiredMessages.push(`All column property 'name's must not be empty.`)
}
}

return requiredMessages.length === 0
}

Expand Down
Loading

0 comments on commit babac3e

Please sign in to comment.