Comments (3)
Approach
As per the underlying Flux philosophy, the SurveyStore
is the one source of truth for all data. It is responsible for maintaining its state and carrying out all mutations as dictated by the order of Actions
that are dispatched to it.
All data in the store is in the form of Immutable.js Maps which means that we need to use the API that the Map interface exposes in order to efficiently query and mutate the data. To this end, there are 3 main methods using which data is mutated - setIn
, updateIn
and deleteIn
. These methods provide an easy way to make deep persistent changes.
The API for these functions looks like this -
Map.setIn([.. array of indices], value)
Map.updateIn([... array of indices], (value) => newValue)
Map.deleteIn([... array of indices])
In order to construct these array
s, the SurveyStore
has it's own suite of helper functions. These helper functions relied on the assumption that blocks are top-level and questions are the immediate children for the block. For example
getQuestionIndex(questionId, block) {
return block.get('questions').findIndex(q => q.get('id') === questionId);
},
Challenge
The challenge now is to rewrite these helpers (& and its calling functions) making no such assumptions of the structure i.e. blocks, questions & options can be nested arbitrarily. Ideally, the signatures of these functions can be like so -
/**
* Returns an array of indices that can be directly go in first arguments to Immutable deep persistent functions.
* @param blockId - id of the block who's index is required
* @param parentBlock (optional) - The parent block at which to begin the search. If left out, the search starts from the top of the survey
*/
function getBlockIndex(blockId, parentBlock = 'top') {
// recursively build the array
}
These functions can then be used like so -
// when adding a new block
let newSurvey = survey.updateIn(this.getBlockIndex(blockId), list =>
list.splice(0, 0, newBlock)
);
// when deleting a block
let newSurvey = survey.deleteIn(this.getBlockIndex(blockId));
// when toggling params
let newSurvey = survey.updateIn(this.getBlockIndex(blockId), b =>
b.set(toggleName, !b.get(toggleName))
);
Similar functions for Questions & Options can be written which expose the same API.
Todo
List of tasks required to complete this feature
- Rewrite
getBlockIndex
to handle nested survey (calledgetBlockPath
) - Rewrite
getQuestionIndex
to handle nested survey (calledgetQuestionPath
) - Refactor the following to use these new functions
- Block add
- Block delete
- Block toggle param
- Question add
- Question edit
- Question delete
- Question toggle param
- Option add
- Option delete
- Block / Subblock / Question Cloning
from react-surveyman.
@etosch - The last part pending in this feature is the ability to allow items to be dragged and dropped on subblocks. I wanted to quickly clarify on what all kinds of interactions should I work on. I have started with an example below -
- Questions inside subblocks should be draggable (outside the block) and droppable (inside the block).
A counter example might be that subblocks
might not be required to be re-orderable inside a Block. Basically, this is to finalize what all functionality is required in the minimap as far as subblocks are concerned.
from react-surveyman.
- Yes, definitely make questions draggable from their blocks to other blocks (top-level or sub). Reordering questions inside a block should have no effect (since they are randomized).
- Perhaps have some way to freeze blocks (both top-level and sub). Sub blocks can float, and it follows from the randomization-first philosophy that we should assume they are floating by default. If someone "freezes" a block, it should be in relation to other blocks within that block's parent.
from react-surveyman.
Related Issues (20)
- Add transitions HOT 2
- Fix id generation HOT 3
- Ability to duplicate blocks and questions
- Validate JSON Schema
- Ability to Save / Load surveys HOT 4
- Allow items to be positioned arbitrarily when being dropped HOT 6
- drop broke in safari HOT 3
- testing slack integration
- randomization button? HOT 5
- Clicking on x in the select component gives a NaN
- Add linting for ES6
- Move to ES6 classes HOT 2
- Apply fixed positioning to the Toolbox
- Add properties to the Question Schema HOT 5
- Broken package HOT 7
- Survey Incremental Validation HOT 13
- License type HOT 3
- s/ordering/ordered
- Several module not found errors HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from react-surveyman.