Skip to content

Commit

Permalink
FairCopy v1.1.3
Browse files Browse the repository at this point in the history
FairCopy v1.1.3
  • Loading branch information
NickLaiacona authored Dec 9, 2022
2 parents 9362b16 + 27ed73b commit 4647a1b
Show file tree
Hide file tree
Showing 55 changed files with 1,302 additions and 535 deletions.
Binary file modified .DS_Store
Binary file not shown.
2 changes: 1 addition & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
"windows": {
"runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron.cmd"
},
"env": { "FAIRCOPY_DEBUG_MODE": "true", "FAIRCOPY_DEV_VERSION": "1.1.1" },
"env": { "FAIRCOPY_DEBUG_MODE": "true", "FAIRCOPY_DEV_VERSION": "1.1.3" },
"program": "${workspaceRoot}/public/electron.js",
"protocol": "inspector",
}
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "faircopy",
"version": "1.1.2",
"version": "1.1.3",
"description": "A word processor for the humanities scholar.",
"main": "public/electron.js",
"private": true,
Expand Down Expand Up @@ -78,7 +78,7 @@
"build": {
"appId": "com.performantsoftware.faircopy",
"productName": "FairCopy",
"copyright": "Copyright © 2021 ${author}",
"copyright": "Copyright © 2022 ${author}",
"files": [
"build/**/*",
"node_modules/**/*"
Expand Down
Binary file added public/.DS_Store
Binary file not shown.
12 changes: 11 additions & 1 deletion public/css/GeneralSettings.css
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#GeneralSettings {
margin: 100px;
margin: 50px;
}

#GeneralSettings .actions {
Expand All @@ -17,4 +17,14 @@

#GeneralSettings .info {
margin-top: 20px;
}

#GeneralSettings .permissions-section {
margin-top: 20px;
margin-bottom: 20px;
padding: 10px;
}

#GeneralSettings .permissions-section ul {
list-style: none;
}
15 changes: 14 additions & 1 deletion public/css/ProjectSettingsWindow.css
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,24 @@
padding: 10px;
}

#ProjectSettingsWindow .window-actions {
#ProjectSettingsWindow .window-actions-right {
padding-right: 20px;
float: right;
}

#ProjectSettingsWindow .window-actions-left {
float: left;
}

#ProjectSettingsWindow .lock-icon {
padding-right: 10px;
}

#ProjectSettingsWindow .action-button {
margin-left: 10px;
}

#ProjectSettingsWindow .error-message {
display:inline-block;
padding-left: 10px;
}
Binary file added public/main-process/.DS_Store
Binary file not shown.
16 changes: 9 additions & 7 deletions public/main-process/FairCopyApplication.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,8 @@ class FairCopyApplication {
ipcMain.on('requestSave', (event, msgID, resourceID, resourceData) => {
const ok = this.fairCopySession.saveResource(resourceID, resourceData)
if( ok ) {
const update = { messageID: msgID, resourceID, resourceData }
this.sendToAllWindows('resourceContentUpdated', resourceID, msgID, update )
const update = { resourceID, messageID: msgID, resourceContent: resourceData }
this.sendToAllWindows('resourceContentUpdated', update )
}
})
ipcMain.on('abandonResourceMap', (event, resourceID) => {
Expand Down Expand Up @@ -148,15 +148,17 @@ class FairCopyApplication {
this.fairCopySession.importEnd()
})

ipcMain.on('checkIn', (event, email, serverURL, projectID, checkInResources, message ) => {
this.fairCopySession.checkIn(email, serverURL, projectID, checkInResources, message)
ipcMain.on('checkIn', (event, userID, serverURL, projectID, checkInResources, message ) => {
this.fairCopySession.checkIn(userID, serverURL, projectID, checkInResources, message)
})

ipcMain.on('checkOut', (event, email, serverURL, projectID, resourceIDs ) => {
this.fairCopySession.checkOut(email, serverURL, projectID, resourceIDs)
ipcMain.on('checkOut', (event, userID, serverURL, projectID, resourceIDs ) => {
this.fairCopySession.checkOut(userID, serverURL, projectID, resourceIDs)
})

ipcMain.on('requestSaveConfig', (event,fairCopyConfig) => { this.fairCopySession.saveFairCopyConfig(fairCopyConfig) })
ipcMain.on('requestSaveConfig', (event,fairCopyConfig,lastAction) => { this.fairCopySession.saveFairCopyConfig(fairCopyConfig,lastAction) })
ipcMain.on('checkInConfig', (event,fairCopyConfig,firstAction) => { this.fairCopySession.checkInConfig(fairCopyConfig,firstAction) })
ipcMain.on('checkOutConfig', (event) => { this.fairCopySession.checkOutConfig() })
ipcMain.on('requestExportConfig', (event,exportPath,fairCopyConfig) => { this.fairCopySession.exportFairCopyConfig(exportPath,fairCopyConfig) })
ipcMain.on('updateProjectInfo', (event,projectInfo) => { this.fairCopySession.updateProjectInfo(projectInfo) })

Expand Down
55 changes: 23 additions & 32 deletions public/main-process/FairCopySession.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ class FairCopySession {

// init remote project if this is one
if( this.remote ) {
const { email, serverURL, projectID } = manifestData
this.remoteProject = new RemoteProject(this, email, serverURL, projectID )
const { userID, serverURL, projectID } = manifestData
this.remoteProject = new RemoteProject(this, userID, serverURL, projectID )
}

this.requestResourceView()
Expand Down Expand Up @@ -315,10 +315,11 @@ class FairCopySession {

// mix in remote project data if needed
if( this.remote ) {
const { email, serverURL } = this.projectStore.manifestData
imageViewData.email = email
const { userID, serverURL, permissions } = this.projectStore.manifestData
imageViewData.userID = userID
imageViewData.serverURL = serverURL
imageViewData.remote = true
imageViewData.permissions = permissions
}
const imageView = this.fairCopyApplication.imageViews[resourceEntry.id]
imageView.webContents.send('imageViewOpened', imageViewData )
Expand All @@ -337,7 +338,7 @@ class FairCopySession {
this.idMapAuthority.sendIDMapUpdate()
}

checkIn(email, serverURL, projectID, checkInResources, message) {
checkIn(userID, serverURL, projectID, checkInResources, message) {
const { resources } = this.projectStore.manifestData
const committedResources = []

Expand All @@ -361,53 +362,43 @@ class FairCopySession {
const resourceEntry = resources[resourceID]
// ignore resources that aren't in local manifest
if( resourceEntry ) {
committedResources.push(createCommitEntry(resourceEntry))

if( resourceEntry.type === 'teidoc' ) {
const doomedIDs = []
// also delete any checked out children
for( const localResource of Object.values(resources) ) {
const { parentResource } = localResource
if( localResource.type !== 'image' && parentResource === resourceEntry.id ) {
// automatically add header and any children if teidoc is deleted
if( resourceEntry.deleted ) {
localResource.deleted = true
committedResources.push(createCommitEntry(localResource))
doomedIDs.push(localResource.id)
} else if( localResource.type === 'header' ) {
committedResources.push(createCommitEntry(localResource))
}
}
}
if( doomedIDs.length > 0 ) {
const idMap = this.idMapAuthority.removeResources(doomedIDs)
this.projectStore.removeResources(doomedIDs,idMap)
}
}
const resourceCommitEntry = createCommitEntry(resourceEntry)
committedResources.push(resourceCommitEntry)
}
if( resourceID === homeParentID ) {
// if this got checked in, move to root
this.resourceViews.home.indexParentID = null
}
}

this.projectStore.checkIn(email, serverURL, projectID, committedResources, message)
this.projectStore.checkIn(userID, serverURL, projectID, committedResources, message)
}

checkOut(email, serverURL, projectID, resourceIDs) {
this.projectStore.checkOut(email, serverURL, projectID, resourceIDs)
checkOut(userID, serverURL, projectID, resourceEntries) {
this.projectStore.checkOut(userID, serverURL, projectID, resourceEntries)
}

saveFairCopyConfig(fairCopyConfig) {
saveFairCopyConfig(fairCopyConfig, lastAction) {
this.projectStore.saveFairCopyConfig(fairCopyConfig, lastAction)
}

checkInConfig(fairCopyConfig, firstAction) {
this.projectStore.saveFairCopyConfig(fairCopyConfig)
this.remoteProject.checkInConfig(fairCopyConfig, firstAction)
}

checkOutConfig() {
this.remoteProject.checkOutConfig()
}

exportFairCopyConfig(exportPath,fairCopyConfig) {
this.projectStore.exportFairCopyConfig(exportPath,fairCopyConfig)
}

updateProjectInfo(projectInfo) {
this.projectStore.updateProjectInfo(projectInfo)
// TODO if this is a remote project, send the latest name and description to server
// permissions etc can only be set from server.
}

requestExport(resourceEntries,path) {
Expand Down
2 changes: 1 addition & 1 deletion public/main-process/IDMapLocal.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class IDMapLocal {
// this map is for unsaved changes made during editing
this.idMapNext = {}
// this is the merged, read-only map
this.idMap = {}
this.idMap = JSON.parse(idMapData)
}

setResourceMap( resourceMap, localID, parentID ) {
Expand Down
4 changes: 2 additions & 2 deletions public/main-process/IDMapRemote.js
Original file line number Diff line number Diff line change
Expand Up @@ -190,8 +190,8 @@ class IDMapRemote {

checkOut( resources ) {
for( const resource of Object.values(resources) ) {
const { parentEntry } = resource
if( parentEntry ) {
const { state, parentEntry } = resource
if( state === 'success' && parentEntry ) {
const { id: parentResourceID, localID: parentLocalID, type: parentType } = parentEntry
if( !this.idMapStaged[parentLocalID] ) this.idMapStaged[parentLocalID] = getBlankResourceMap(parentResourceID, parentType)
}
Expand Down
73 changes: 42 additions & 31 deletions public/main-process/ProjectStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,13 +99,15 @@ class ProjectStore {
return
}
const teiSchema = fs.readFileSync(`${baseDir}/config/tei-simple.json`).toString('utf-8')
const baseConfig = fs.readFileSync(`${baseDir}/config/faircopy-config.json`).toString('utf-8')
const baseConfigJSON = fs.readFileSync(`${baseDir}/config/faircopy-config.json`).toString('utf-8')

if( !teiSchema || !baseConfig ) {
if( !teiSchema || !baseConfigJSON ) {
log.info('Application data is missing or corrupted.')
return
}

this.baseConfig = JSON.parse(baseConfigJSON)

let { fairCopyManifest, fairCopyConfig, idMap, projectFilePath } = project

if( !fairCopyManifest || !fairCopyConfig || !idMap ) {
Expand All @@ -114,11 +116,7 @@ class ProjectStore {
}

// project store keeps a copy of the manifest data
this.manifestData = JSON.parse(fairCopyManifest)
if( !this.manifestData ) {
log.info('Error parsing project manifest.')
return
}
this.manifestData = fairCopyManifest

const currentVersion = this.fairCopyApplication.config.version
if( !this.fairCopyApplication.isDebugMode() && !compatibleProject(this.manifestData, currentVersion) ) {
Expand All @@ -132,8 +130,8 @@ class ProjectStore {
this.manifestData = migrateManifestData(this.manifestData)

// if elements changed in config, migrate project config
this.migratedConfig = migrateConfig(this.manifestData.generatedWith,baseConfig,fairCopyConfig)
fairCopyConfig = this.migratedConfig
migrateConfig(this.manifestData.generatedWith,this.baseConfig,fairCopyConfig)
this.migratedConfig = fairCopyConfig

// apply any migrations to ID Map data
idMap = migrateIDMap(this.manifestData.generatedWith,idMap,this.manifestData.resources)
Expand All @@ -145,7 +143,7 @@ class ProjectStore {
})
}

const projectData = { projectFilePath, fairCopyManifest: JSON.stringify(this.manifestData), teiSchema, fairCopyConfig, baseConfig, idMap }
const projectData = { projectFilePath, fairCopyManifest: this.manifestData, teiSchema, fairCopyConfig, baseConfig: this.baseConfig, idMap }
this.onProjectOpened( projectData )
}

Expand Down Expand Up @@ -181,8 +179,8 @@ class ProjectStore {
}

requestExport(resourceEntries,path) {
const { resources: localEntries, remote, email, serverURL, projectID } = this.manifestData
const projectData = { localEntries, remote, email, serverURL, projectID }
const { resources: localEntries, remote, userID, serverURL, projectID } = this.manifestData
const projectData = { localEntries, remote, userID, serverURL, projectID }
for( const resourceEntry of resourceEntries ) {
this.projectArchiveWorker.postMessage({ messageType: 'request-export', resourceEntry, projectData, path })
}
Expand Down Expand Up @@ -286,10 +284,18 @@ class ProjectStore {
this.projectArchiveWorker.postMessage({ messageType: 'write-file', fileID: idMapEntryName, data: idMap })
}

saveFairCopyConfig( fairCopyConfig ) {
saveFairCopyConfig( fairCopyConfig, lastAction=null ) {
this.migratedConfig = null
this.projectArchiveWorker.postMessage({ messageType: 'write-file', fileID: configSettingsEntryName, data: fairCopyConfig })
this.saveManifest()
if( lastAction ) {
this.manifestData.configLastAction = lastAction
}
const configData = JSON.stringify(fairCopyConfig)
if( configData && configData.length > 0 ) {
this.projectArchiveWorker.postMessage({ messageType: 'write-file', fileID: configSettingsEntryName, data: configData })
this.saveManifest()
} else {
log.error(`Cannot save empty FairCopy Config.`)
}
}

save() {
Expand All @@ -312,20 +318,20 @@ class ProjectStore {
}
}

updateProjectInfo(projectInfoJSON) {
const projectInfo = JSON.parse(projectInfoJSON)
const { name, description } = projectInfo
updateProjectInfo(projectInfo) {
const { name, description, permissions } = projectInfo
this.manifestData.projectName = name
this.manifestData.description = description
this.manifestData.permissions = permissions
this.saveManifest()
}

checkIn(email, serverURL, projectID, committedResources, message) {
this.projectArchiveWorker.postMessage({ messageType: 'check-in', email, serverURL, projectID, committedResources, message })
checkIn(userID, serverURL, projectID, committedResources, message) {
this.projectArchiveWorker.postMessage({ messageType: 'check-in', userID, serverURL, projectID, committedResources, message })
}

checkOut(email, serverURL, projectID, resourceIDs ) {
this.projectArchiveWorker.postMessage({ messageType: 'check-out', email, serverURL, projectID, resourceIDs })
checkOut(userID, serverURL, projectID, resourceEntries ) {
this.projectArchiveWorker.postMessage({ messageType: 'check-out', userID, serverURL, projectID, resourceEntries })
}

openImageResource(requestURL) {
Expand All @@ -347,31 +353,36 @@ class ProjectStore {
}
}

checkOutResults(resources,error) {
this.fairCopyApplication.sendToMainWindow('checkOutResults', Object.keys(resources), error )
checkOutResults(resources,error) {
const checkOutStatus = []
for( const resource of Object.values(resources) ) {
const { resourceEntry, parentEntry, content } = resource
this.manifestData.resources[resourceEntry.id] = resourceEntry
this.fairCopyApplication.sendToAllWindows('resourceEntryUpdated', resourceEntry )
this.fairCopyApplication.sendToAllWindows('resourceEntryUpdated', parentEntry )
this.fairCopyApplication.sendToAllWindows('resourceContentUpdated', resourceEntry.id, 'check-out-messsage', content )
const { state, resourceEntry, parentEntry, content } = resource
if( state === 'success') {
this.manifestData.resources[resourceEntry.id] = resourceEntry
this.fairCopyApplication.sendToAllWindows('resourceEntryUpdated', resourceEntry )
this.fairCopyApplication.sendToAllWindows('resourceEntryUpdated', parentEntry )
this.fairCopyApplication.sendToAllWindows('resourceContentUpdated', { resourceID: resourceEntry.id, messageID: 'check-out-messsage', resourceContent: content })
}
checkOutStatus.push({ state, resourceEntry })
}
const idMap = this.fairCopyApplication.fairCopySession.idMapAuthority.checkOut(resources)
this.projectArchiveWorker.postMessage({ messageType: 'write-file', fileID: idMapEntryName, data: idMap })
this.saveManifest()

this.fairCopyApplication.sendToMainWindow('checkOutResults', checkOutStatus, error )
this.fairCopyApplication.fairCopySession.requestResourceView()
}

checkInResults(resourceStatus, error) {
const { email } = this.manifestData
const { userID } = this.manifestData
const resourceEntries = []
for( const resourceID of Object.keys(resourceStatus) ) {
const resourceEntry = this.manifestData.resources[resourceID]
if( !error ) {
// remove remote resources from project file and manifest, update all windows
this.projectArchiveWorker.postMessage({ messageType: 'remove-file', fileID: resourceID })
resourceEntry.local = false
resourceEntry.lastAction = { action_type: 'check_in', user: { email } }
resourceEntry.lastAction = { action_type: 'check_in', user: { id: userID } }
this.fairCopyApplication.sendToAllWindows('resourceEntryUpdated', resourceEntry )
delete this.manifestData.resources[resourceID]
}
Expand Down
Loading

0 comments on commit 4647a1b

Please sign in to comment.