a1f9fe5a86
This preview is as yet unformatted...but stay tuned; we're soon to
add Markdown! 😉
228 lines
4.6 KiB
Svelte
228 lines
4.6 KiB
Svelte
<script>
|
|
import Importabular from "importabular"
|
|
|
|
let editor
|
|
|
|
let emailContent = 'Hi [TK name],\n\nIt\'s been a while since we heard from you. How are you doing? Your last article [TK article] did quite well, and we were wondering if you\'d be interested in writing a sequel?\n\nCheers,\nThe Snipette Team[TK PS]'
|
|
|
|
let sheetOne
|
|
let step = 0
|
|
let tkList = []
|
|
|
|
let cookiePreviewText = ''
|
|
let cookiePreviewRow = 0
|
|
|
|
function showEmail() {
|
|
step = 1
|
|
}
|
|
|
|
function detectFields(value) {
|
|
if (!value) return []
|
|
|
|
let matches = value.match(/\[TK (\w+?)\]/gm)
|
|
let tkList = []
|
|
|
|
if (!!matches) {
|
|
let propertyRegex = new RegExp(/\[TK (\w+)\]/)
|
|
for (let m of matches) {
|
|
tkList.push(propertyRegex.exec(m)[1])
|
|
}
|
|
}
|
|
|
|
return tkList
|
|
}
|
|
|
|
$: tkList = detectFields(emailContent)
|
|
|
|
function showSheet() {
|
|
// Figure out columns
|
|
let columns = []
|
|
|
|
if (!tkList.includes('email')) {
|
|
columns.push({
|
|
label: 'email',
|
|
description: 'Email address of the recipient',
|
|
placeholder: 'someone@members.snipettemag.com',
|
|
})
|
|
}
|
|
|
|
for (let tk of tkList) {
|
|
columns.push({
|
|
label: tk,
|
|
})
|
|
}
|
|
|
|
// First sheet
|
|
sheetOne = new Importabular({
|
|
node: editor,
|
|
columns: columns,
|
|
onChange(data) {
|
|
cookiePreviewText = getPreview()
|
|
}
|
|
})
|
|
|
|
step = 2
|
|
|
|
// for debugging only
|
|
window.sheetOne = sheetOne
|
|
}
|
|
|
|
function incrementPreviewRow() {
|
|
let sheetLength = sheetOne.getData().length
|
|
|
|
// make sure it's not too big...
|
|
if (cookiePreviewRow >= sheetLength-1) {
|
|
cookiePreviewRow = sheetLength - 1
|
|
} else if (cookiePreviewRow < 0) {
|
|
// ...and not too small
|
|
cookiePreviewRow = 0
|
|
} else {
|
|
// if not, then make it "just right"! :)
|
|
cookiePreviewRow++
|
|
}
|
|
}
|
|
|
|
function decrementPreviewRow() {
|
|
let sheetLength = sheetOne.getData().length
|
|
// make sure it's not too small...
|
|
if (cookiePreviewRow >= sheetLength) {
|
|
// ...and not too big
|
|
cookiePreviewRow = sheetLength - 1
|
|
} else if (cookiePreviewRow <= 0) {
|
|
// if not, then make it "just right"! :)
|
|
cookiePreviewRow = 0
|
|
} else {
|
|
cookiePreviewRow--
|
|
}
|
|
}
|
|
|
|
function getPreview(row) {
|
|
if (!row) row = cookiePreviewRow
|
|
let previewText = emailContent
|
|
|
|
// get the row we're working on
|
|
if (!sheetOne) return '' // no sheet to get data from :(
|
|
let data = sheetOne.getData()
|
|
if (row < 0 || data.length < row) return previewText // no row to apply :(
|
|
let r = data[row]
|
|
|
|
for (let tk of tkList) {
|
|
// figure out which column holds values for this TK
|
|
let tkIndex = window.sheetOne.columns.findIndex(t => t.label == tk)
|
|
|
|
// replace it!
|
|
previewText = previewText.replace(new RegExp(`\\[TK ${tk}\\]`, 'g'), r[tkIndex])
|
|
}
|
|
|
|
return previewText
|
|
}
|
|
|
|
// automatically update
|
|
$: cookiePreviewText = getPreview(cookiePreviewRow)
|
|
|
|
function next() {
|
|
step += 1
|
|
}
|
|
</script>
|
|
|
|
<main>
|
|
<img src="/assets/email-baker.png" class="main-pic" alt="Email Oven"/>
|
|
<h1>Chip <span class="highlight">Choc</span></h1>
|
|
<h2>Cookie-cutter emails made easy.</h2>
|
|
|
|
{#if step != 0}
|
|
<h3 class="mt-3">Step {step}</h3>
|
|
{/if}
|
|
|
|
{#if step == 0}
|
|
<button on:click={showEmail}>Start Drafting</button>
|
|
{/if}
|
|
|
|
{#if step == 1}
|
|
<div class="instructions">
|
|
<p>Compose your email below, leaving [TK stuff] to be replaced in the table. Make sure each TK is a single word: no spaces allowed!</p>
|
|
</div>
|
|
<div class="email-content">
|
|
<textarea bind:value={emailContent}/>
|
|
<p>
|
|
<strong>Detected fields:</strong>
|
|
{#each tkList as tk (tk)}
|
|
<span class="tag">{tk}</span>
|
|
{/each}
|
|
</p>
|
|
</div>
|
|
{/if}
|
|
|
|
{#if step >= 2}
|
|
<div class="instructions">
|
|
<p>Now, fill in the fields for each user. (You can also copy-paste rows and columns directly from Air, if the ordering is right!)</p>
|
|
</div>
|
|
{/if}
|
|
<div id="editor" bind:this={editor}></div>
|
|
|
|
{#if step == 1}
|
|
<button on:click={showSheet}>Next</button>
|
|
{/if}
|
|
|
|
{#if step == 2}
|
|
<button on:click={decrementPreviewRow}>< Prev</button>
|
|
<button on:click={incrementPreviewRow}>Next ></button>
|
|
<pre id="cookiePreview">{cookiePreviewText}</pre>
|
|
{/if}
|
|
|
|
</main>
|
|
|
|
<style>
|
|
main {
|
|
text-align: center;
|
|
padding: 1em;
|
|
max-width: 240px;
|
|
margin: 0 auto;
|
|
}
|
|
|
|
h1 {
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
h1 + h2 {
|
|
margin-top: 0;
|
|
}
|
|
|
|
.main-pic {
|
|
max-width: 100%;
|
|
}
|
|
|
|
@media (min-width: 640px) {
|
|
main {
|
|
max-width: none;
|
|
}
|
|
|
|
.main-pic {
|
|
max-width: 240px;
|
|
}
|
|
}
|
|
|
|
.instructions {
|
|
max-width: 640px;
|
|
margin: 0 auto;
|
|
}
|
|
|
|
.email-content {
|
|
margin: 4em auto;
|
|
}
|
|
|
|
.email-content textarea {
|
|
width: 100%;
|
|
max-width: 640px;
|
|
font-family: inherit;
|
|
min-height: 15em;
|
|
}
|
|
|
|
.tag {
|
|
margin: 0.2em;
|
|
padding: 0.5em 1em 0.5em 1em;
|
|
background: #ffe3ff;
|
|
border-radius: 1em;
|
|
}
|
|
</style>
|