forked from cadey/xesite
view my resume
This commit is contained in:
parent
0315c0b721
commit
dba3ae46f8
|
@ -36,7 +36,10 @@ func (p Posts) Less(i, j int) bool {
|
|||
}
|
||||
func (p Posts) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
|
||||
|
||||
var posts Posts
|
||||
var (
|
||||
posts Posts
|
||||
rbody string
|
||||
)
|
||||
|
||||
func init() {
|
||||
err := filepath.Walk("./blog/", func(path string, info os.FileInfo, err error) error {
|
||||
|
@ -87,6 +90,13 @@ func init() {
|
|||
}
|
||||
|
||||
sort.Sort(sort.Reverse(posts))
|
||||
|
||||
resume, err := ioutil.ReadFile("./static/resume/resume.md")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
rbody = string(resume)
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
@ -109,6 +119,13 @@ func main() {
|
|||
fail:
|
||||
http.Error(w, "Not Found", http.StatusNotFound)
|
||||
})
|
||||
http.HandleFunc("/api/resume", func(w http.ResponseWriter, r *http.Request) {
|
||||
json.NewEncoder(w).Encode(struct {
|
||||
Body string `json:"body"`
|
||||
}{
|
||||
Body: rbody,
|
||||
})
|
||||
})
|
||||
http.Handle("/dist/", http.FileServer(http.Dir("./frontend/static/")))
|
||||
http.Handle("/static/", http.FileServer(http.Dir(".")))
|
||||
http.HandleFunc("/", writeIndexHTML)
|
||||
|
|
|
@ -82,5 +82,5 @@ view state =
|
|||
[]
|
||||
[ h1 [] [ text "Posts" ]
|
||||
, documentTitle [ title "Posts - Christine Dodrill" ] []
|
||||
, p [] [ text state.status ]
|
||||
, div [ className "row" ] $ map post state.posts ]
|
||||
, div [ className "row" ] $ map post state.posts
|
||||
, p [] [ text state.status ] ]
|
||||
|
|
|
@ -3,6 +3,7 @@ module App.Layout where
|
|||
import App.BlogEntry as BlogEntry
|
||||
import App.BlogIndex as BlogIndex
|
||||
import App.Counter as Counter
|
||||
import App.Resume as Resume
|
||||
import App.Routes (Route(..))
|
||||
import Control.Monad.RWS (state)
|
||||
import DOM (DOM)
|
||||
|
@ -20,20 +21,23 @@ data Action
|
|||
= Child (Counter.Action)
|
||||
| BIChild (BlogIndex.Action)
|
||||
| BEChild (BlogEntry.Action)
|
||||
| REChild (Resume.Action)
|
||||
| PageView Route
|
||||
|
||||
type State =
|
||||
{ route :: Route
|
||||
, count :: Counter.State
|
||||
, bistate :: BlogIndex.State
|
||||
, bestate :: BlogEntry.State }
|
||||
, bestate :: BlogEntry.State
|
||||
, restate :: Resume.State }
|
||||
|
||||
init :: State
|
||||
init =
|
||||
{ route: NotFound
|
||||
, count: Counter.init
|
||||
, bistate: BlogIndex.init
|
||||
, bestate: BlogEntry.init }
|
||||
, bestate: BlogEntry.init
|
||||
, restate: Resume.init }
|
||||
|
||||
update :: Action -> State -> EffModel State Action (ajax :: AJAX, dom :: DOM)
|
||||
update (PageView route) state = routeEffects route $ state { route = route }
|
||||
|
@ -43,14 +47,19 @@ update (BIChild action) state = BlogIndex.update action state.bistate
|
|||
update (BEChild action) state = BlogEntry.update action state.bestate
|
||||
# mapState (state { bestate = _ })
|
||||
# mapEffects BEChild
|
||||
update (REChild action) state = Resume.update action state.restate
|
||||
# mapState ( state { restate = _ })
|
||||
# mapEffects REChild
|
||||
update (Child action) state = noEffects $ state { count = Counter.update action state.count }
|
||||
update _ state = noEffects $ state
|
||||
|
||||
routeEffects :: Route -> State -> EffModel State Action (dom :: DOM, ajax :: AJAX)
|
||||
routeEffects BlogIndex state = { state: state
|
||||
routeEffects (BlogIndex) state = { state: state
|
||||
, effects: [ pure BlogIndex.RequestPosts ] } # mapEffects BIChild
|
||||
routeEffects (BlogPost page) state = { state: state { bestate = BlogEntry.init { name = page } }
|
||||
, effects: [ pure BlogEntry.RequestPost ] } # mapEffects BEChild
|
||||
routeEffects (Resume) state = { state: state
|
||||
, effects: [ pure Resume.RequestResume ] } # mapEffects REChild
|
||||
routeEffects (BlogPost page') state = { state: state { bestate = BlogEntry.init { name = page' } }
|
||||
, effects: [ pure BlogEntry.RequestPost ] } # mapEffects BEChild
|
||||
routeEffects _ state = noEffects $ state
|
||||
|
||||
view :: State -> Html Action
|
||||
|
@ -162,7 +171,7 @@ index =
|
|||
page :: Route -> State -> Html Action
|
||||
page NotFound _ = h1 [] [ text "not found" ]
|
||||
page Home _ = index
|
||||
page Resume state = h1 [] [ text "Christine Dodrill" ]
|
||||
page Resume state = map REChild $ Resume.view state.restate
|
||||
page BlogIndex state = map BIChild $ BlogIndex.view state.bistate
|
||||
page (BlogPost _) state = map BEChild $ BlogEntry.view state.bestate
|
||||
page ContactPage _ = contact
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
module App.Resume where
|
||||
|
||||
import App.Utils (mdify)
|
||||
import Control.Monad.Aff (attempt)
|
||||
import DOM (DOM)
|
||||
import Data.Argonaut (class DecodeJson, decodeJson, (.?))
|
||||
import Data.Either (Either(..), either)
|
||||
import Data.Maybe (Maybe(..))
|
||||
import Network.HTTP.Affjax (AJAX, get)
|
||||
import Prelude (Unit, bind, pure, show, unit, ($), (<>), (<<<))
|
||||
import Pux (noEffects, EffModel)
|
||||
import Pux.DocumentTitle (documentTitle)
|
||||
import Pux.Html (Html, a, div, h1, p, text)
|
||||
import Pux.Html.Attributes (href, dangerouslySetInnerHTML, className, id_, title)
|
||||
|
||||
data Action = RequestResume
|
||||
| ReceiveResume (Either String Resume)
|
||||
|
||||
type State =
|
||||
{ status :: String
|
||||
, err :: String
|
||||
, resume :: Maybe Resume }
|
||||
|
||||
data Resume = Resume
|
||||
{ body :: String }
|
||||
|
||||
instance decodeJsonResume :: DecodeJson Resume where
|
||||
decodeJson json = do
|
||||
obj <- decodeJson json
|
||||
body <- obj .? "body"
|
||||
pure $ Resume { body: body }
|
||||
|
||||
init :: State
|
||||
init =
|
||||
{ status: "Loading..."
|
||||
, err: ""
|
||||
, resume: Nothing }
|
||||
|
||||
update :: Action -> State -> EffModel State Action (ajax :: AJAX, dom :: DOM)
|
||||
update (ReceiveResume (Left err)) state =
|
||||
noEffects $ state { resume = Nothing, status = "Error in fetching resume, please use the plain text link below.", err = err }
|
||||
update (ReceiveResume (Right body)) state =
|
||||
noEffects $ state { status = "", err = "", resume = Just body }
|
||||
where
|
||||
got' = Just unit
|
||||
update RequestResume state =
|
||||
{ state: state
|
||||
, effects: [ do
|
||||
res <- attempt $ get "/api/resume"
|
||||
let decode r = decodeJson r.response :: Either String Resume
|
||||
let resume = either (Left <<< show) decode res
|
||||
pure $ ReceiveResume resume
|
||||
]
|
||||
}
|
||||
|
||||
view :: State -> Html Action
|
||||
view { status: status, err: err, resume: resume } =
|
||||
case resume of
|
||||
Nothing -> div [] [ text status, p [] [ text err ] ]
|
||||
(Just (Resume resume')) ->
|
||||
div [ className "row" ]
|
||||
[ documentTitle [ title "Resume - Christine Dodrill" ] []
|
||||
, div [ className "col s8 offset-s2" ]
|
||||
[ p [ className "browser-default", dangerouslySetInnerHTML $ mdify resume'.body ] []
|
||||
, a [ href "/static/resume/resume.md" ] [ text "Plain-text version of this resume here" ], text "." ]
|
||||
]
|
|
@ -27,3 +27,5 @@ match url = fromMaybe NotFound $ router url $
|
|||
BlogPost <$> (lit "blog" *> str) <* end
|
||||
<|>
|
||||
ContactPage <$ lit "contact" <* end
|
||||
<|>
|
||||
Resume <$ lit "resume" <* end
|
||||
|
|
|
@ -0,0 +1,132 @@
|
|||
# Christine Dodrill
|
||||
|
||||
---
|
||||
|
||||
> #### Rockstar Hacker, Cloud Architect, Gopher, Haskeller, Container Expert
|
||||
> ##### Mountain View, CA   [christine.website][homepage]   [@theprincessxena][twitter] ![twit][]
|
||||
> `Docker`, `Git`, `Haskell`, `Nim`, `Go`, `C`, `CentOS`, `CoreOS`, `IRC`, `Matrix`
|
||||
|
||||
---
|
||||
> **"** A github power user, constantly learns new things to keep up on what's new in tech.
|
||||
|
||||
|
||||
---
|
||||
## Experience
|
||||
#### Backplane.io - Software Engineer   <small>*2016 - 2016*</small>
|
||||
`Go`, `Docker`, `docker-compose`, `devops`, `PostgreSQL`
|
||||
> [Backplane](https://backplane.io) is an innovative reverse reverse proxy that
|
||||
> helps administrators and startups simplify their web application routing.
|
||||
>
|
||||
> #### Highlights
|
||||
>
|
||||
> - Performance monitoring of production servers
|
||||
> - Continuous deployment and development in Go
|
||||
> - Learning a lot about HTTP/2 and load balancing
|
||||
|
||||
---
|
||||
#### IMVU - Site Reliability Engineer   <small>*2015 - 2016*</small>
|
||||
`Ubuntu Server`, `CFEngine`, `Haskell`, `Go`, `Perl`, `Nginx`, `JunOS`, `Ceph`, `MySQL`, `Redis`, `Memcached`, `PHP`, `Erlang`
|
||||
> IMVU, inc is a company whose mission is to help people find and communicate
|
||||
> with eachother. Their main product is a 3D avatar-based chat client and its
|
||||
> surrounding infrastructure allowing creators to make content for the avatars
|
||||
> to wear.
|
||||
>
|
||||
> #### Highlights
|
||||
>
|
||||
> - Wrote up technical designs
|
||||
> - Implemented technical designs on an over 800 machine cluster
|
||||
> - Continuous learning of a lot of very powerful systems and improving upon them
|
||||
> when it is needed
|
||||
|
||||
---
|
||||
#### VTCSecure - Deis Consultant (contract)   <small>*2014 - 2015*</small>
|
||||
`Deis`, `Docker`, `CoreOS`, `Go`, `Freeswitch`
|
||||
> VTCSecure is a company dedicated to helping with custom and standard
|
||||
> audio/video conferencing solutions. They specialize in helping the deaf and
|
||||
> blind communicate over today's infrastructure without any trouble on their end.
|
||||
>
|
||||
> #### Highlights
|
||||
>
|
||||
> - Started groundwork for a dynamically scalable infrastructure on a project for helping the blind see things
|
||||
> - Developed a prototype of a new website for VTCSecure
|
||||
> - Education on best practices using Docker and CoreOS
|
||||
> - Learning Freeswitch
|
||||
|
||||
---
|
||||
#### Crowdflower - Deis Consultant (Contract)   <small>*2014 - 2014*</small>
|
||||
`Ruby`, `Rails`, `Chef`, `CoreOS`, `Docker`, `Deis`
|
||||
> Crowdflower is a company that uses crowdsourcing to have its customers submit
|
||||
> tasks to be done, similar to Amazon's Mechanical Turk. CrowdFlower has over 50
|
||||
> labor channel partners, and its network has more than 5 million contributors
|
||||
> worldwide.
|
||||
>
|
||||
> #### Highlights
|
||||
>
|
||||
> - Research and development on scalable Linux deployments on AWS via CoreOS and
|
||||
> Docker
|
||||
> - Development of in-house tools to speed instance creation
|
||||
> - Laid groundwork on the creation and use of better tools for managing large
|
||||
> clusters of CoreOS and Fleet machines
|
||||
|
||||
---
|
||||
#### OpDemand - Software Engineering Intern   <small>*2014 - 2014*</small>
|
||||
`Deis`, `CoreOS`, `Go`, `Docker`
|
||||
> OpDemand is the company behind the open source project Deis, a distributed
|
||||
> platform-as-a-service (PaaS) designed from the ground up to emulate Heroku but
|
||||
> on privately owned servers.
|
||||
>
|
||||
> #### Highlights
|
||||
>
|
||||
> - Built new base image for Deis components
|
||||
> - Research and development on a new builder component
|
||||
|
||||
---
|
||||
## Open Source
|
||||
#### [Elemental-IRCd](http://elemental-ircd.com)
|
||||
A scalable RFC compliant IRCv3 enabled IRC server for personal and professional use.
|
||||
|
||||
#### Accomplishments
|
||||
|
||||
* Automated testing via [Travis](https://travis-ci.org/Elemental-IRCd/elemental-ircd)
|
||||
* Community management via [Github](https://github.com/elemental-ircd/elemental-ircd)
|
||||
|
||||
Elemental is currently in use in production on several networks, totaling 800-1000
|
||||
users per day with spikes of up to 50,000 on special events.
|
||||
|
||||
---
|
||||
#### [Tetra](https://github.com/Xe/Tetra)
|
||||
A modern IRC services platform for TS6 IRC daemons.
|
||||
|
||||
#### Accomplishments
|
||||
|
||||
* Parallel, safe execution of handlers and scripts
|
||||
* Moonscript -> Lua transpiling support
|
||||
* A clean, declarative domain-specific language for declaring features or bot commands:
|
||||
|
||||
```
|
||||
Command "PING", ->
|
||||
"PONG"
|
||||
```
|
||||
|
||||
This will create a command named "PING" that will return "PONG" to the user when it is used.
|
||||
|
||||
---
|
||||
#### [PonyAPI](https://github.com/Xe/ponyapi)
|
||||
A simple API for information on episodes of My Little Pony: Friendship is Magic written in Nim to be run inside a container.
|
||||
|
||||
All data is loaded into ram and there are no usage limits as long as you agree to not take down the server it is running on.
|
||||
|
||||
---
|
||||
#### [Professional Projects](https://github.com/Xe)
|
||||
Projects here will be of a more professional nature (save a few here and there).
|
||||
|
||||
---
|
||||
## Writing
|
||||
|
||||
> Articles listed below will be either personal or professional and do not reflect the views of any company or group I am affiliated with. The writing is my own.
|
||||
#### [My Blog](https://christine.website/blog) *<small>@christine.website/blog</small>*
|
||||
|
||||
---
|
||||
[homepage]: https://christine.website
|
||||
[twitter]: https://twitter.com/theprincessxena
|
||||
[twit]: http://cdn-careers.sstatic.net/careers/Img/icon-twitter.png?v=b1bd58ad2034
|
Loading…
Reference in New Issue