Skip to content

Commit c6b68df

Browse files
committed
* Feature complete!
1 parent b12d78d commit c6b68df

10 files changed

Lines changed: 168 additions & 83 deletions

File tree

README.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,16 @@
11
# Mach-E VIN Finder
2-
Mach-E VIN Finder.
2+
by [John "Seg" Seggerson](https://seg.fyi/).
3+
4+
### Publicly Accessible URL
5+
https://seg.fyi/mach-e/
6+
7+
### Notes
8+
This project lets one find a VIN number in their Ford Mach-E Reservation data. It's basic and subject to change as the Ford website changes, but it will get the job done.
9+
10+
[You can report issues if things aren't working](https://github.com/TheSeg/mache-vin-finder/issues), and pull requests will be entertained.
311

412
## Project setup
13+
If you wish to run the project on your own computer, it's a basic Node with Vue setup.
514
```
615
npm install
716
```

src/App.vue

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,20 @@
11
<template>
2-
<div class="container-fluid">
3-
<Introduction />
4-
<Preperation />
5-
<Instructions />
6-
<Data />
7-
<Results v-if="mainData" />
2+
<div>
3+
<nav class="navbar navbar-dark bg-primary sticky-top">
4+
<div class="container-fluid">
5+
<div class="navbar-brand">Ford Mach-E Reservation Details Viewer</div>
6+
</div>
7+
</nav>
8+
<div class="container-fluid">
9+
<Introduction />
10+
<hr>
11+
<Preperation />
12+
<hr>
13+
<Instructions />
14+
<hr>
15+
<Data />
16+
<Results v-show="mainData" />
17+
</div>
818
</div>
919
</template>
1020

src/components/00_Introduction.vue

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
<template>
2-
<div class="row">
2+
<div class="row justify-content-center mt-3">
33
<div class="col-10">
44
<h1>Ford Mach-E Reservation Details Viewer</h1>
5-
<p>This is a tool helps obtain various information from your Mach-E reservation that is sent to your browser, but not displayed. Espeically the VIN number, if your order has a build week set.</p>
5+
<p>This is a tool helps obtain various information from your Mach-E reservation that is sent to your browser, but not displayed. Espeically the VIN number, if your order has a build week set. Created by <a href="https://seg.fyi/" target="_blank">John "Seg" Seggerson</a>.</p>
66
<h2 class="text-danger">Disclaimers!</h2>
7-
<p><strong>This tool is not from Ford.</strong> I've done my best to preserve your privacy as much as possiable. After obtaining all the data from visiting this page, no data is sent from your browser to this or any other website. Not even analytics. That's why some of the steps are convoluted.</p>
8-
<p>The software that runs this site is <a href="https://github.com/TheSeg/mache-vin-finder" target="_blank">located on my GitHub</a>. If you're adventerous, you can run it on your computer yourself. <a href="https://github.com/TheSeg/mache-vin-finder/issues" target="_blank">I'm open to improvments</a>, but ultimately this site is AS-IS.</p>
7+
<p><strong>This tool is not from Ford.</strong> Use at your own risk, etc.</p>
8+
<p><strong>Data you enter stays on your computer.</strong> I've done my best to preserve your privacy as much as possiable. No data is sent from your browser to this or any other website. Not even analytics.</p>
9+
<p>The software source code is <a href="https://github.com/TheSeg/mache-vin-finder" target="_blank">located on my GitHub</a>. If you're adventerous, you can run it on your computer yourself! <a href="https://github.com/TheSeg/mache-vin-finder/issues" target="_blank">I'm open to improvments</a>, but ultimately this site is AS-IS.</p>
910
</div>
1011
</div>
1112
</template>

src/components/01_Preperation.vue

Lines changed: 8 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,23 @@
11
<template>
2-
<div class="row">
2+
<div class="row justify-content-center">
33
<div class="col-10">
44
<h2>Preperation</h2>
5-
<p><strong>Keep this tab open!</strong> You'll be flipping between this tab and your reservation page.</p>
6-
<p>We're going to be using your browser's developer tools in order to get a payload of data. The tools may be something new to you, but follow along with the instructions and you'll be fine.</p>
7-
<div class="mb-3">
8-
<label for="browserInput" class="form-label">Browser Make</label>
9-
<select class="form-control" id="browserInput" aria-describedby="browserInputHelp" v-model="this.$store.state.selectedBrowser">
10-
<option v-for="option in browserOptions" :value="option.value" :key="option.value">{{ option.text }}</option>
11-
</select>
12-
<div id="browserInputHelp" class="form-text">I'll adjust the instructions based on what browser you're using. If yours isn't listed, then I don't have specific instructions for you yet.</div>
13-
</div>
5+
<p>We're going to be using your <em>desktop or laptop</em> browser's developer tools in order to get a payload of data. The tools may be something new to you, but follow along with the instructions and you'll be fine.</p>
6+
<h3>Keep this tab open!</h3>
7+
<p>You'll be flipping between this tab and your reservation page.</p>
8+
<h3>Reservation Number</h3>
9+
<p>If you want to make this easier, put in your Order Number in the field below.</p>
1410
<div class="mb-3">
1511
<label for="orderNumberInput" class="form-label">Mach-E Reservation Order Number</label>
1612
<input type="number" class="form-control" id="orderNumberInput" aria-describedby="orderNumberInputHelp" v-model="this.$store.state.ordernumber" placeholder="XXXXXXXX">
17-
<div id="orderNumberInputHelp" class="form-text">Not required, but it helps make the instructions easier.</div>
13+
<div id="orderNumberInputHelp" class="form-text">This entire tool works in your browser so your data stays in your browser.</div>
1814
</div>
1915
</div>
2016
</div>
2117
</template>
2218

2319
<script>
2420
export default {
25-
name: 'Preperation',
26-
data () {
27-
return {
28-
browserOptions: [
29-
{
30-
text: 'Chrome',
31-
value: 'chrome'
32-
},
33-
{
34-
text: 'FireFox',
35-
value: 'firefox'
36-
}
37-
]
38-
}
39-
}
21+
name: 'Preperation'
4022
}
4123
</script>

src/components/02_Instructions.vue

Lines changed: 66 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
<template>
2-
<div class="row">
2+
<div class="row justify-content-center">
33
<div class="col-10">
44
<h2>Instructions</h2>
5+
56
<h3 class="h5">1. Open your Reservation in a new tab and log into your Ford account.</h3>
67
<div v-if="this.$store.state.ordernumber">
78
<p>Since you entered your order number, start here: <a :href="'https://www.ford.com/buy/mach-e/manage.html?reservationId=' + this.$store.state.ordernumber" target="_blank">https://www.ford.com/buy/mach-e/manage.html?reservationId={{this.$store.state.ordernumber}}</a></p>
@@ -11,24 +12,82 @@
1112
<p>Go to your Ford Reservation page to find your order: <a href="https://www.ford.com/buy/reservations/#/?gnav=header-account">https://www.ford.com/buy/reservations/#/?gnav=header-account</a></p>
1213
<p>You will need to log into your Ford account associated with your order. You should be able to return to the reservataion listing and select your Mach-E reservation. You can also put the order number in the above to update these instructions.</p>
1314
</div>
15+
1416
<h3 class="h5">2. Check status of order.</h3>
15-
<div class="row">
17+
<div class="row justify-content-center">
1618
<div class="col">
17-
<p>Check to make sure your order is "Scheduled For Production" with a date. See the image as an example.</p>
19+
<p>Check to make sure your order is "Scheduled For Production" with a date.</p>
20+
<p>If your order is still waiting for a production date/week, you can not get your VIN number. It's assigned only when your car is scheduled for production.</p>
1821
</div>
19-
<div class="col-5">
22+
<div class="col-3">
2023
<p><img src="../assets/ScheduledForProduction.png" class="img-thumbnail"></p>
2124
</div>
2225
</div>
26+
2327
<h3 class="h5">3. Open Developer Tools.</h3>
24-
<p>For this step, we're going to open up your browser's developer tools. This will be different across different browser types, so please select the browser you wish to use.</p>
25-
<h3 class="h5">4. TODO</h3>
28+
<p>For this step, we're going to open up your browser's developer tools. These steps work for Chrome and Firefox unless noted.</p>
29+
<ol>
30+
<li>Hit the Keyboard shortcut of <code>F12</code> or on macOS, <code>FN + F12</code>
31+
<ul>
32+
<li>This will open the developer's pannel.</li>
33+
</ul>
34+
</li>
35+
<li>Find the "Network" tab in the developer's pannel.
36+
<ul>
37+
<li>You may have to click on a <code>&gt;&gt;</code> button to reveal the "Network" tab.</li>
38+
</ul>
39+
</li>
40+
<li>Click the <code>XHR</code> filter button.
41+
<ul>
42+
<li>This is in a row with buttons labled "All", "HTML", "CSS", "JS", etc.</li>
43+
</ul>
44+
</li>
45+
</ol>
46+
47+
<h3 class="h5">4. Refresh the page.</h3>
48+
<p>With the network tools open, your browser will give detailed data of what is downloaded from the website. There's going to be a lot, so wait till the page finishes loading completely.</p>
49+
50+
<h3 class="h5">5. Find the data payload.</h3>
51+
<p><em>This is the hard part.</em> There are a lot of entries in the network panel. We're looking for one that starts with your order number.</p>
52+
<ul class="list-unstyled">
53+
<li>
54+
<strong>Display:</strong> <code>{{ordernumber || 'XXXXXXXX'}}?lang=en_us</code>
55+
</li>
56+
<li>
57+
<strong>Full URL:</strong> <code>https://apigtw.ford.com/oneford/api/gep/USA/reservations/{{ordernumber || 'XXXXXXXX'}}?lang=en_us</code>
58+
</li>
59+
<li v-if="!ordernumber" class="text-muted">Replace the X's with your order number.</li>
60+
</ul>
61+
<p>When you find it, click on that entry once.</p>
62+
63+
<h3 class="h5">6. Copy the response to this form.</h3>
64+
<p>A new pane should appear. One of the tabs inside this pane should be called <code>Response</code>. You may have to click on a <code>&gt;&gt;</code> button to reveal the option. Click the <code>Response</code> tab.</p>
65+
<p><em><strong>Note for Firefox:</strong></em> Next, expand the <code>Response Payload</code> section.</p>
66+
<p>You should see a long string of characters and text. <em>This is what we're looking for!</em></p>
67+
68+
<ul>
69+
<li>Click once anywhere in this long block of text.</li>
70+
<li>Select all the contents by hitting <code>Ctrl-A</code> or <code>Command-A</code>.</li>
71+
<li>Copy the contents by hitting <code>Ctrl-C</code> or <code>Command-C</code>.</li>
72+
</ul>
73+
74+
<h3 class="h5">7. Now paste the content in the box below!</h3>
75+
<ul>
76+
<li>Click the inside of the input box once.</li>
77+
<li>Hit the keys: <code>Ctrl-V</code> or <code>Command-V</code>.</li>
78+
</ul>
79+
2680
</div>
2781
</div>
2882
</template>
2983

3084
<script>
85+
import { mapState } from 'vuex'
86+
3187
export default {
32-
name: 'Instructions'
88+
name: 'Instructions',
89+
computed: {
90+
...mapState(['ordernumber'])
91+
}
3392
}
3493
</script>

src/components/03_Data.vue

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
<template>
2-
<div class="row">
3-
<div class="col-10">
2+
<div class="row justify-content-center">
3+
<div class="col-10 pb-5">
44
<h2>Data Entry</h2>
55
<form>
66
<div class="mb-2">
77
<label for="mainData" class="form-label">Paste the contents of the response inside this text box.</label>
88
<textarea class="form-control" id="mainData" rows="3" v-model="this.textData"></textarea>
9-
<div id="mainDataHelp" aria-describedby="mainDataHelp" class="form-text">It's OK to not see it all, just as long as it's a direct copy/paste of <em>all</em> the contents.</div>
9+
<p v-if="errors" class="text-danger">Sorry! That wasn't proper JSON content. Are you sure you copied the entire response text?</p>
10+
<p v-else class="text-muted">Don't worry how it's formatted in this box.</p>
1011
</div>
1112
<div class="mb-2">
1213
<button type="button" class="btn btn-primary btn-lg" @click="processJSON">Process</button>
13-
<!-- <button type="reset" class="btn btn-danger">Reset</button> -->
1414
</div>
1515
</form>
1616
</div>
@@ -24,21 +24,32 @@
2424
</style>
2525

2626
<script>
27+
import { Modal } from 'bootstrap'
28+
2729
export default {
2830
name: 'Data',
2931
data () {
3032
return {
31-
textData: null
33+
textData: null,
34+
errors: false
3235
}
3336
},
3437
methods: {
3538
processJSON (event) {
36-
console.info('Processing Stuff')
37-
const processed = JSON.parse(this.textData)
38-
if (processed) {
39-
this.$store.state.mainData = processed
40-
} else {
39+
this.errors = false
40+
try {
41+
const processed = JSON.parse(this.textData)
42+
if (processed) {
43+
this.$store.state.mainData = processed
44+
const myModal = new Modal(document.getElementById('finalDataModal'))
45+
myModal.show()
46+
} else {
47+
// Error times!
48+
this.errors = true
49+
}
50+
} catch (error) {
4151
// Error times!
52+
this.errors = true
4253
}
4354
}
4455
}

src/components/04_Results.vue

Lines changed: 30 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,51 @@
11
<template>
2-
<div class="row">
3-
<div class="col-10">
4-
<h2>Results</h2>
5-
<div v-if="mainData">
6-
<h3>Success!</h3>
7-
<table class="table" v-for="(entry) in mainData.entries" :key="entry.product.code">
8-
<tbody>
9-
<tr>
10-
<th>VIN</th>
11-
<td class="h5"><code class="user-select-all" v-html="entry.product.vin"></code></td>
12-
</tr>
13-
<tr>
14-
<th>VIN barcode:</th>
15-
<td>
16-
<svg class="barcode" jsbarcode-format="CODE128" jsbarcode-displayvalue="false" :jsbarcode-value="entry.product.vin"></svg>
17-
</td>
18-
</tr>
19-
</tbody>
20-
</table>
21-
</div>
22-
<div v-else>
23-
Still need proper data.
2+
<div class="modal fade" id="finalDataModal" tabindex="-1" aria-hidden="true">
3+
<div class="modal-dialog modal-dialog-centered modal-dialog-scrollable modal-xl">
4+
<div class="modal-content">
5+
<div class="modal-header">
6+
<h5 class="modal-title">Data Results</h5>
7+
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
8+
</div>
9+
<div class="modal-body">
10+
<div v-if="mainData">
11+
<div v-for="(entry) in mainData.entries" :key="entry.product.code">
12+
<div class="text-center" v-if="entry.product.vin">
13+
<h2 class="text-center"><code class="user-select-all" v-html="entry.product.vin"></code></h2>
14+
</div>
15+
<div class="px-2 my-3 text-center">
16+
<svg class="barcode img-fluid" jsbarcode-format="CODE128" jsbarcode-displayvalue="false" :jsbarcode-value="entry.product.vin"></svg>
17+
</div>
18+
</div>
19+
<div class="text-center">
20+
<p class="fw-light">Use the barcode to scan your VIN number into the FordPass&reg; app.</p>
21+
<p class="h3">Enjoy your Ford Mustang Mach-E!</p>
22+
</div>
23+
</div>
24+
<div v-else>
25+
Still need proper data.
26+
</div>
27+
</div>
28+
<div class="modal-footer">
29+
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
30+
</div>
2431
</div>
2532
</div>
2633
</div>
2734
</template>
2835

2936
<script>
30-
import JsBarcode from 'jsbarcode'
3137
import { mapState } from 'vuex'
38+
import JsBarcode from 'jsbarcode'
3239
3340
export default {
3441
name: 'Results',
3542
computed: {
3643
...mapState(['mainData'])
3744
},
3845
mounted () {
39-
console.info('mounted')
4046
JsBarcode('.barcode').init()
4147
},
4248
updated () {
43-
console.info('updated')
4449
JsBarcode('.barcode').init()
4550
}
4651
}

src/store/index.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ export default createStore({
44
state () {
55
return {
66
ordernumber: null,
7-
selectedBrowser: 'chrome',
87
mainData: null
98
}
109
},

src/styles/_bootstrap.scss

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
// @import "../../node_modules/bootstrap/scss/dropdown";
2525
// @import "../../node_modules/bootstrap/scss/button-group";
2626
// @import "../../node_modules/bootstrap/scss/nav";
27-
// @import "../../node_modules/bootstrap/scss/navbar";
27+
@import "../../node_modules/bootstrap/scss/navbar";
2828
// @import "../../node_modules/bootstrap/scss/card";
2929
// @import "../../node_modules/bootstrap/scss/accordion";
3030
// @import "../../node_modules/bootstrap/scss/breadcrumb";
@@ -33,9 +33,9 @@
3333
// @import "../../node_modules/bootstrap/scss/alert";
3434
// @import "../../node_modules/bootstrap/scss/progress";
3535
// @import "../../node_modules/bootstrap/scss/list-group";
36-
// @import "../../node_modules/bootstrap/scss/close";
36+
@import "../../node_modules/bootstrap/scss/close";
3737
// @import "../../node_modules/bootstrap/scss/toasts";
38-
// @import "../../node_modules/bootstrap/scss/modal";
38+
@import "../../node_modules/bootstrap/scss/modal";
3939
// @import "../../node_modules/bootstrap/scss/tooltip";
4040
// @import "../../node_modules/bootstrap/scss/popover";
4141
// @import "../../node_modules/bootstrap/scss/carousel";

src/styles/_variables.scss

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
$body-bg: #111;
2+
$body-color: #fff;
3+
$link-color: #ccc;
4+
5+
$modal-content-color: #000;
6+
$modal-content-bg: #fff;
7+
8+
$enable-shadows: true;
9+
$enable-gradients: true;

0 commit comments

Comments
 (0)