Slide 1

Slide 1 text

nystudio107 / @nystudio107 by Andrew Welch devMode podcast / devMode.fm Solving Problems with Modern Tooling

Slide 2

Slide 2 text

Problems

Slide 3

Slide 3 text

Math Problems

Slide 4

Slide 4 text

Word Problems

Slide 5

Slide 5 text

Relationship Problems

Slide 6

Slide 6 text

And yet…

Slide 7

Slide 7 text

That’s What We Do

Slide 8

Slide 8 text

We Solve Other People’s Problems

Slide 9

Slide 9 text

We Solve Other People’s Problems

Slide 10

Slide 10 text

We Solve Other People’s Problems

Slide 11

Slide 11 text

Client Problems, AMIRITE?

Slide 12

Slide 12 text

Standing on a Mountain

Slide 13

Slide 13 text

Standing on a Mountain of Solved Problems Standing on a Mountain

Slide 14

Slide 14 text

This Old Site

Slide 15

Slide 15 text

This Old Site

Slide 16

Slide 16 text

This Old Site Custom website built in Cake PHP

Slide 17

Slide 17 text

This Old Site Database of food- borne illnesses dating back to 1993

Slide 18

Slide 18 text

This Old Site (They just didn’t want it to look like it was from 1993)

Slide 19

Slide 19 text

No content

Slide 20

Slide 20 text

Project Goals

Slide 21

Slide 21 text

Project Goals Make the outbreak database easier to maintain for the content authors

Slide 22

Slide 22 text

Project Goals Make the frontend easier to use by researchers and journalists

Slide 23

Slide 23 text

Project Goals Modernize the website underpinnings

Slide 24

Slide 24 text

Potentially provide an API to allow other parties to access the database directly Project Goals

Slide 25

Slide 25 text

Modern Tooling

Slide 26

Slide 26 text

Vue.js Modern Tooling

Slide 27

Slide 27 text

Modern Tooling Vuex

Slide 28

Slide 28 text

Modern Tooling Axios

Slide 29

Slide 29 text

GraphQL Modern Tooling

Slide 30

Slide 30 text

Modern Tooling Tailwind CSS

Slide 31

Slide 31 text

Modern Tooling Craft CMS

Slide 32

Slide 32 text

Shiny New Site

Slide 33

Slide 33 text

No content

Slide 34

Slide 34 text

Eliminate the SERP

Slide 35

Slide 35 text

// Home page import { OutbreakMixins } from '../mixins/outbreak.js'; import '@trevoreyre/autocomplete-vue/dist/style.css' import { createStore } from '../store/store.js'; // App main const main = async() => { // Async load the vue module const [ Vue, VueSmoothScroll ] = await Promise.all([ import(/* webpackChunkName: "vue" */ 'vue'), import(/* webpackChunkName: "vue" */ 'vue2-smooth-scroll'), ]); const store = await createStore(Vue.default); Vue.default.use(VueSmoothScroll.default); // Create our vue instance const vm = new Vue.default({ render: (h) => { return h('search-form'); }, mixins: [OutbreakMixins], store, components: { 'search-form': () => import(/* webpackChunkName: "searchform" */ '../../vue/SearchForm.vue'), }, }); return vm; }; home.js

Slide 36

Slide 36 text

import * as actions from './actions.js'; import * as mutations from './mutations.js'; import * as getters from './getters.js'; // Store main export const createStore = async(Vue) => { const { default: Vuex } = await import(/* webpackChunkName: "vuex" */ 'vuex'); Vue.use(Vuex); return new Vuex.Store({ state: { csrf: null, gqlToken: null, outbreakSlug: null, outbreakDetail: null, states: null, vehicles: null, searchForm: null, organisms: null, outbreaks: null, months: null, countries: null, }, getters, mutations, actions, modules: {} }); }; store.js

Slide 37

Slide 37 text

Auto-Complete Component

Slide 38

Slide 38 text

  • {{ result[titleField] }}
  • Autocomplete.vue

    Slide 39

    Slide 39 text

    gql.js // Configure the GraphQL api endpoint export const configureGqlApi = (url, token) => ({ baseURL: url, headers: { 'X-Requested-With': 'XMLHttpRequest', ...(token && { 'Authorization': `Bearer ${token}` }), } }); // Execute a GraphQL query by sending an XHR to our api endpoint export const executeGqlQuery = async(api, query, variables, callback) => { // Execute the GQL query try { const response = await api.post('', { query: query, variables: variables }); if (callback && response.data.data) { callback(response.data.data); } // Log any errors if (response.data.errors) { console.error(response.data.errors); } } catch (error) { console.error(error); } };

    Slide 40

    Slide 40 text

    export const outbreaksQuery = (additionalParams) => { let queryAdditionalParams = ''; let entryAdditionalParams = ''; additionalParams.forEach((item) =>{ queryAdditionalParams += `, $${item.fieldName}: [QueryArgument]`; entryAdditionalParams += `, ${item.fieldName}: $${item.fieldName}`; }); return ` query outbreaksQuery($needle: String!${queryAdditionalParams}) { entries(section: "outbreaks", search: $needle${entryAdditionalParams}) { title, url, slug, ...on outbreaks_outbreaks_Entry { summary, beginningDate, vehicles { title }, organisms { title }, tags { title } } } } `; queries.js

    Slide 41

    Slide 41 text

    No content

    Slide 42

    Slide 42 text

    Live Demo??

    Slide 43

    Slide 43 text

    devMode podcast / devMode.fm nystudio107.com @nystudio107 SpeakerDeck.com/ nystudio107