Skip to content

Commit 451a5cb

Browse files
authored
Merge pull request #15 from swiftype/jasonstoltz/updated-readme
Added a high-level code overview to README
2 parents 75a4f1c + 887bb34 commit 451a5cb

File tree

1 file changed

+145
-11
lines changed

1 file changed

+145
-11
lines changed

README.md

Lines changed: 145 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -47,17 +47,17 @@ and then restart this app.
4747

4848
The following is a complete list of options available for configuration in [engine.json](src/config/engine.json).
4949

50-
| option | value type | required/optional | source
51-
| --- | --- | --- | --- |
52-
| `engineName` | String | required | Found in your [App Search Dashboard](http://app.swiftype.com/as). |
53-
| `hostIdentifier` | String | required | Found in your [App Search Dashboard](http://app.swiftype.com/as). |
54-
| `searchKey` | String | required | Found in your [App Search Dashboard](http://app.swiftype.com/as). |
55-
| `fields` | Array[String] | required | A list of fields that will be searched and displayed within your results. |
56-
| `titleField` | String | optional | The field to display as the title in results. |
57-
| `urlField` | String | optional | A field with a url to use as a link in results. |
58-
| `urlFieldTemplate` | String | optional | Instead of urlField, you can provide a URL "template" here, which lets you build a URL from other fields. ex: "https://www.example.com/{{id}}". |
59-
| `sortFields` | Array[String] | required | A list of fields that will be used for sort options. |
60-
| `facets` | Array[String] | required | A list of fields that will be available as "facet" filters. Read more about facets within the [App Search documentation](https://swiftype.com/documentation/app-search/guides/facets). |
50+
| option | value type | required/optional | source |
51+
| ------------------ | ------------- | ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
52+
| `engineName` | String | required | Found in your [App Search Dashboard](http://app.swiftype.com/as). |
53+
| `hostIdentifier` | String | required | Found in your [App Search Dashboard](http://app.swiftype.com/as). |
54+
| `searchKey` | String | required | Found in your [App Search Dashboard](http://app.swiftype.com/as). |
55+
| `fields` | Array[String] | required | A list of fields that will be searched and displayed within your results. |
56+
| `titleField` | String | optional | The field to display as the title in results. |
57+
| `urlField` | String | optional | A field with a url to use as a link in results. |
58+
| `urlFieldTemplate` | String | optional | Instead of urlField, you can provide a URL "template" here, which lets you build a URL from other fields. ex: "https://www.example.com/{{id}}". |
59+
| `sortFields` | Array[String] | required | A list of fields that will be used for sort options. |
60+
| `facets` | Array[String] | required | A list of fields that will be available as "facet" filters. Read more about facets within the [App Search documentation](https://swiftype.com/documentation/app-search/guides/facets). |
6161

6262
### External configuration
6363

@@ -76,3 +76,137 @@ rename it to `engine.json` and configure with your Engine's specific details.
7676
```bash
7777
cp src/config/engine.json.example src/config/engine.json
7878
```
79+
80+
## Understanding the Reference UI Code
81+
82+
In addition to previewing your data in a UI, this project can also be used as a code reference. Here's a quick primer on this project's code setup, to help you understand how it's put together.
83+
84+
Logically, the pieces of this application fit together like this:
85+
86+
```
87+
------------------
88+
| App Search API |
89+
------------------
90+
^
91+
|
92+
|
93+
( State manager ) ( Syncs state with URL )
94+
------------------- --------------
95+
| AppSearchDriver | <--> | URLManager |
96+
------------------- --------------
97+
|
98+
| actions / state
99+
v
100+
---------------------
101+
| AppSearchProvider | ( Driver to React glue )
102+
---------------------
103+
|
104+
| context
105+
v
106+
--------------
107+
| Containers | ( Behavior )
108+
--------------
109+
|
110+
|
111+
--------------
112+
| Components | ( View )
113+
--------------
114+
```
115+
116+
That corresponds to the code and file structure in the following way:
117+
118+
**src/app-search**
119+
120+
This holds the `AppSearchDriver`, the `URLManager`, and `AppSearchProvider`
121+
from the diagram above. This is where all of the core application logic lives.
122+
The interface to all of this logic is a set of "actions" and "state" that are
123+
passed down in a React [Context](https://reactjs.org/docs/context.html). Those
124+
actions and state are then consumed by Components and Containers.
125+
126+
If you've used Redux before, this concept should sound familiar.
127+
128+
_state_ - All of the core "state" of the applications is managed in a single store
129+
at the top level. ex:
130+
131+
```
132+
{
133+
current: 1, // The current page in pagination
134+
searchTerm: "", // The current search term
135+
results: [], // Results of the current search
136+
...
137+
}
138+
```
139+
140+
_actions_ - Actions are how you change the state:
141+
142+
```
143+
addFilter: () => { ... },
144+
removeFilter: () => { ... },
145+
setSearchTerm: : () => { ... },
146+
```
147+
148+
Calling an action will typically:
149+
150+
1. Make a call the App Search API with the new query details.
151+
2. Update `results` in state with the results of the new query.
152+
3. Update the url with the new query details.
153+
4. Notify listeners that state changed (i.e., pass updated `results` as props
154+
to components so they can re-render)
155+
156+
So, for instance, a `SearchBox` component might be wired up to call the
157+
`setSearchTerm` action with updated terms any time a user submits a search box
158+
value. A `Results` component could then simply iterate through the `results`
159+
from state to render search results.
160+
161+
Everything in this directory for now should be thought of as a separate library.
162+
The goal eventually is to actually separate this out into a library of it's own,
163+
so when composing a UI you'd simply need to focus on creating components
164+
from actions and state, and not all of the plumbing that goes into managing
165+
that state. For now though, it's included in this reference as a pattern
166+
that can be followed.
167+
168+
**src/containers**
169+
170+
Components in this UI are separated into "Containers" and "Components". These
171+
can be thought of as "Logic" and "View", respectively.
172+
173+
"Containers" are "connected" to the "context" via a "Higher Order Component"
174+
(HOC) `withAppSearch`. This HOC simply exposes all state and actions as `props`.
175+
A consuming Container simply accesses those actions and state, composes
176+
appropriate handlers and data as props and passes them to the appropriate
177+
Component.
178+
179+
**src/components**
180+
181+
Components are simply view templates. They take `props` and render
182+
them in markup. They have no state of their own.
183+
184+
**src/config**
185+
186+
Being that this is a "generic" UI that is usable with any engine via
187+
configuration, it should be no surprise that there is a fair amount of logic
188+
around that. Configuration logic is not very useful for a code reference,
189+
so the majority of that logic is encapsulated here to keep other code
190+
references clean.
191+
192+
## Customization
193+
194+
It should be feasible to use this project as a starting point for your
195+
own implementation. Here are a few places to look to make changes:
196+
197+
- The styles for the entire project can be found in [src/styles](src/styles).
198+
Simple style tweaks changes can be made here, or you could replace these styles
199+
with your own.
200+
- [src/components](src/components) contains the view templates for
201+
components. Structural HTML changes can be made here.
202+
- If you find that you have different data or behavior requirements for
203+
existing components, you can customize the component Containers in
204+
[src/containers](src/containers).
205+
- If you find you have requirements that none of the existing components
206+
satisfy, you could create an entirely new component and/or container. Use the
207+
`withAppSearch` HOC in order to access any action or state.
208+
- Lastly, if you find there is a core action or state missing, you may
209+
consider updating the core logic in [src/app-search](src/app-search).
210+
211+
Lastly, we accept PRs! If you make a customization that you think would benefit
212+
others, please feel free to contribute it back.

0 commit comments

Comments
 (0)