| 1 | {{define "app_new"}}{{template "top" .}} |
| 2 | {{if .Flash}}<p class="banner">{{.Flash}}</p>{{end}} |
| 3 | {{if .FlashErr}}<p class="banner error">{{.FlashErr}}</p>{{end}} |
| 4 | <div class="pagehead"> |
| 5 | <p class="eyebrow">Account · {{.Account.Name}}</p> |
| 6 | <h1>Create an app</h1> |
| 7 | <p class="lede">Claim a name here; ship a release to it from your terminal.</p> |
| 8 | </div> |
| 9 | <form class="signin" method="post" action="{{.Base}}/apps/new"> |
| 10 | <input type="hidden" name="csrf" value="{{.CSRF}}"> |
| 11 | <label class="visually-hidden" for="app-name">App name</label> |
| 12 | <input id="app-name" type="text" name="name" placeholder="my-app" autofocus |
| 13 | required pattern="[A-Za-z][A-Za-z0-9-]{0,31}" maxlength="32">{{with .RegionPicker}} |
| 14 | <label for="app-region">{{$.RegionCopy.PickerLabel}}</label> |
| 15 | <select id="app-region" name="region"> |
| 16 | <option value="@auto" selected>{{.Auto}}</option> |
| 17 | {{range .Options}}<option value="{{.Value}}">{{.Label}}</option>{{end}} |
| 18 | </select> |
| 19 | <input type="hidden" name="tz" value=""> |
| 20 | <p class="small">{{$.RegionCopy.PickerHelp}}</p> |
| 21 | {{if .Attribution}}<p class="small"><a href="{{.AttributionURL}}">{{.AttributionText}}</a></p>{{end}} |
| 22 | <script> |
| 23 | // Enhancement only: with JS off the server's IP-or-home guess stands. |
| 24 | // Fills the tz hint and relabels ONLY the @auto option; its value stays |
| 25 | // "@auto" so the server still knows the person did not choose. |
| 26 | (function () { |
| 27 | var f = document.currentScript.closest("form"), sel = f.elements.region, tz = ""; |
| 28 | var label = {{printf $.RegionCopy.AutoOption "%PLACE%"}}; |
| 29 | try { tz = Intl.DateTimeFormat().resolvedOptions().timeZone || ""; } catch (e) {} |
| 30 | f.elements.tz.value = tz; |
| 31 | if (!tz) return; |
| 32 | var body = new URLSearchParams({ csrf: f.elements.csrf.value, tz: tz }); |
| 33 | fetch("{{$.Base}}/apps/new/region", { method: "POST", body: body, credentials: "same-origin" }) |
| 34 | .then(function (r) { return r.ok ? r.json() : null; }) |
| 35 | .then(function (g) { |
| 36 | if (!g || sel.value !== "@auto") return; |
| 37 | sel.options[0].text = label.replace("%PLACE%", g.name); |
| 38 | }) |
| 39 | .catch(function () {}); |
| 40 | })(); |
| 41 | </script>{{end}} |
| 42 | <button type="submit">Create app</button> |
| 43 | </form> |
| 44 | <p class="small">Names are lowercase letters, digits, and dashes, starting with a letter — unique within this account, not across the platform.</p> |
| 45 | {{template "bottom" .}}{{end}} |
| 46 | |