Skip to content

Commit

Permalink
Improvements to attribute drawer form and function.
Browse files Browse the repository at this point in the history
* use facs attr

* delete sample image

* update readme

* add version number

* improve text styling

* don't activate refs

* put attr drawer on top

* make attr drawer disappear when not in use

* improve layout of attr drawer

* display multiple els

* deal w nodes properly

* attribute drawer should appear on the bottom in note pop up

* render all attrs

* attr field layout

* improve definitions

* hi control wip

* add select field support

* fix blank key

* switch from dagger to sticky

* note windows always on top
  • Loading branch information
NickLaiacona authored Nov 4, 2019
1 parent efe9bd7 commit 0bb279e
Show file tree
Hide file tree
Showing 17 changed files with 3,099 additions and 193 deletions.
8 changes: 3 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,8 @@ Developer Environment

To run Faircopy in development mode, install the necessary dependencies using `yarn` and then `yarn start-dev`. This will start the create react app server on port 3000. To run the electron main process on VS Code, a debug configuration has been created for the project. Run the debugger and this will allow you to work in the electron environment. Create React App will hot reload into Electron's browser as you work.

To build the React application for packaging, run:
To create a distributable version of the application, run:

`yarn build`
`yarn dist`

To run the built React app:

`yarn start`
The installers will be created in the `dist` folder.
2 changes: 1 addition & 1 deletion public/css/CETEIcean.css
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ tei-anchor {
/* Empty Rule Set */
}
tei-app {
/* Empty Rule Set */
/* Empty `ule Set */
}
tei-app tei-note {
display: none;
Expand Down
20 changes: 12 additions & 8 deletions public/css/ParameterDrawer.css
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
.drawerHeader {
padding: 10px;
background: #D8D8D8;
.attributePanel {
border: 1px solid #ddd;
margin-top: 3px;
}

.drawerBody {
background: #F7F6F6;
padding: 5px;
.attributeSelectField {
min-width: 300px;
}

.attrTextField {
margin: 5px;
max-width: 80%;
min-width: 300px;
margin: 10px;
}

.attributeFields {
display: flex;
flex-wrap: wrap;
}
15 changes: 11 additions & 4 deletions public/css/TEIEditor.css
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,19 @@
min-width: calc( 100% - 12px);
}

.TEIEditor .status-bar {
.TEIEditor .dialogPlane {
position: fixed;
top: 70px;
left: 30px;
width: 80%;
}

.TEIEditor .dialogPlaneNote {
position: fixed;
bottom: 0;
width: 100%;
background: #ccc;
bottom: 0px;
margin-bottom: 5px;
left: 30px;
width: 80%;
}

.save-button {
Expand Down
60 changes: 60 additions & 0 deletions public/css/TEIElementStyles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/* language support */
/* render Arabic, Persian, Ottoman, Hebrew as rtl */
[lang = "ar"],
[lang = "ota"],
[lang = "fa"],
[lang = "he"],
[lang *="-Arab-AR"]{
direction:rtl;
text-align:right;
}
/* display latin scripts as ltr */
[lang = "en"],
[lang = "fr"],
[lang = "de"],
[lang = "it"],
[lang *="ar-Latn-"],
[lang *="ota-Latn-"]{
direction:ltr;
text-align:left;
}

/* Phrase level markup styling is based on information layers */
[phraselvl = "true"] {
border-bottom: dotted;
}

/* p */
tei-p {
display: block;
margin-top: 10px;
margin-bottom: 10px;
text-align: justify;
}

tei-pb {
margin-right: 3px;
margin-left: 3px;
}

tei-note {
margin-right: 3px;
margin-left: 3px;
}

tei-hi[rend="caps"] {
text-transform: uppercase;
}
tei-hi[rend="italic"] {
font-style: italic;
}
tei-hi[rend="bold"] {
font-weight: bold;
}

.ProseMirror {
/* font-family: "Lucida Grande", "Cardo", "Arial Unicode MS","Galilee Unicode Gk", "New Athena Unicode", "Athena Unicode", "Palatino Linotype", "Titus Cyberbit Basic", "Vusillus Old Face", "Alphabetum", "Galatia SIL", "Code 2000", "GentiumAlt", "Gentium", "Minion Pro", "GeorgiaGreek", "Vusillus Old Face Italic", "Everson Mono", "Aristarcoj", "Porson", "Legendum", "Aisa Unicode", "Hindsight Unicode", "Caslon", "Verdana", "Tahoma"; */
font-size: 14pt;
line-height: 1.4em;
}

2 changes: 1 addition & 1 deletion public/css/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
@import "root.css";

@import "EditorGutter.css";
@import "CETEIcean.css";
@import "TEIElementStyles.css";
@import "ParameterDrawer.css";
@import "ProseMirrorComponent.css";
@import "TEIEditor.css";
Expand Down
Binary file removed public/img/leaf.png
Binary file not shown.
1 change: 1 addition & 0 deletions public/main-process/ApplicationWindowManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ class ApplicationWindowManager {

// Create the browser window
const browserWindow = new BrowserWindow({
parent: this.mainWindow,
width: 700,
height: 500,
frame: false,
Expand Down
195 changes: 121 additions & 74 deletions src/components/ParameterDrawer.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
import React, { Component } from 'react';
import { Drawer, TextField } from '@material-ui/core'
import { Button } from '@material-ui/core'
import { TextField } from '@material-ui/core'
import { Button, Fade, FormControl, InputLabel, Select, MenuItem } from '@material-ui/core'
import { Node } from "prosemirror-model"

import ExpansionPanel from '@material-ui/core/ExpansionPanel';
import ExpansionPanelSummary from '@material-ui/core/ExpansionPanelSummary';
import ExpansionPanelDetails from '@material-ui/core/ExpansionPanelDetails';
import Typography from '@material-ui/core/Typography';
import ExpandMoreIcon from '@material-ui/icons/ExpandMore';

import { changeAttribute } from "../tei-document/commands"

const {ipcRenderer} = window.nodeAppDependencies.ipcRenderer
Expand All @@ -23,100 +29,141 @@ export default class ParameterDrawer extends Component {
}
}

renderSelectField(element,fieldKey,key,attr,attrSpec) {

const menuOptions = [ <MenuItem key={`${fieldKey}----`} value={""}>{"<none>"}</MenuItem> ]
for( const option of attrSpec.options ) {
menuOptions.push( <MenuItem key={`${fieldKey}-${option}`} value={option}>{option}</MenuItem>)
}

return (
<FormControl id={fieldKey}>
<InputLabel>{key}</InputLabel>
<Select
className="attributeSelectField"
value={attr}
fullWidth={true}
onChange={this.changeAttributeHandler(element,key)}
>
{ menuOptions }
</Select>
</FormControl>
)
}

renderAttributes(element) {
const {attrs} = element
const elementName = element.type.name
const keys = Object.keys(attrs)
const {teiDocumentFile} = this.props
const elementSpec = teiDocumentFile.elementSpecs[elementName]
const defaultAttrSpec = teiDocumentFile.defaultAttrSpec

if( keys.length === 0 ) {
return (
<div className='drawerBody'>
This element has no attributes.
</div>
)
} else {
const key = keys[0]
const attr = attrs[key]
return (
<div className='drawerBody'>
<TextField
id={`attr-${key}`}
label={key}
value={attr}
className="attrTextField"
fullWidth={true}
onChange={this.changeAttributeHandler(element,key)}
/>
let attrFields = []
for( const key of keys ) {
const fieldKey = `attr-${key}`
const attr = attrs[key] ? attrs[key] : ""
const attrSpec = (elementSpec.attrs && elementSpec.attrs[key]) ? elementSpec.attrs[key] : defaultAttrSpec
attrFields.push(
<div className="attrTextField" key={fieldKey} >
{ attrSpec.type === 'select' ?
this.renderSelectField(element,fieldKey,key,attr,attrSpec)
:
<TextField
id={fieldKey}
label={key}
value={attr}
fullWidth={true}
onChange={this.changeAttributeHandler(element,key)}
/>
}
</div>
)
}
}

return ( attrFields ?
<div className="attributeFields">
{attrFields}
</div>
: <Typography>This element has no attributes.</Typography>
)
}

renderNoteButton( element ) {
isPhraseLevel( element ) {
if( !element ) return false
const name = element.type.name
return (name === 'hi' || name === 'ref' || name === 'name')
}

// must be a ref mark
if( element.type.name !== 'ref' ) {
return null
}
// renderNoteButton( element ) {

// // must be a ref mark
// if( element.type.name !== 'ref' ) {
// return null
// }

const target = element.attrs['target']
// const target = element.attrs['target']

if( localStorage.getItem(target) ) {
const editNote = () => {
ipcRenderer.send( 'createNoteEditorWindow', target )
}
// if( localStorage.getItem(target) ) {
// const editNote = () => {
// ipcRenderer.send( 'createNoteEditorWindow', target )
// }

return (
<Button onClick={editNote} variant='contained' tooltip='Edit Note'>Edit Note</Button>
)
// return (
// <Button onClick={editNote} variant='contained' tooltip='Edit Note'>Edit Note</Button>
// )

}
// }
// }

renderElement(element,key) {
const { elementSpecs } = this.props.teiDocumentFile
const name = element.type.name

return (
<ExpansionPanel key={key} elevation={2} className="attributePanel" >
<ExpansionPanelSummary
expandIcon={<ExpandMoreIcon />}
aria-controls={`${key}-content`}
id={`${key}-header`}
>
<Typography><b>{name}</b>: <i>{elementSpecs[name].docs}</i> </Typography>
</ExpansionPanelSummary>
<ExpansionPanelDetails >
{ this.renderAttributes(element) }
</ExpansionPanelDetails>
</ExpansionPanel>
)
}

renderElement() {
const { docs } = this.props.teiDocumentFile
render() {
const selection = (this.props.editorState) ? this.props.editorState.selection : null

let element
// create a list of the selected phrase level elements
let elements = []
if( selection ) {
const { $anchor } = selection
const marks = $anchor.marks()
let mark = marks.length > 0 ? marks[0] : null
element = (selection.node) ? selection.node : (mark) ? mark : $anchor.parent
if( selection.node ) {
elements.push( this.renderElement(selection.node,'attr-panel-node') )
} else {
const { $anchor } = selection
const marks = $anchor.marks()
let count = 0
for( const mark of marks ) {
if( this.isPhraseLevel(mark) ) {
const key = `attr-panel-${count++}`
elements.push( this.renderElement(mark,key) )
}
}
}
}

if( !element ) {
return (
<div>
<div className='drawerHeader'>
Select an element to inspect its attributes.
</div>
</div>
)
} else {
const name = element.type.name
return (
return (
<Fade in={elements.length > 0} >
<div>
<div className='drawerHeader'>
{name} - {docs[name]}
</div>
{ this.renderAttributes(element) }
{ elements }
</div>
)
}
</Fade>
)
}

render() {
// TODO When activated, drawer pulls out and focus is given to the first field
// may be minimized
return (
<Drawer
className='ParameterDrawer'
variant="persistent"
anchor="bottom"
open={true}
>
{ this.renderElement() }
</Drawer>
)
}
}
Loading

0 comments on commit 0bb279e

Please sign in to comment.