chipchoc/src/App.svelte
Badri Sunderarajan 0291dcacd3 Remove duplicates from TK list to avoid crashes
Otherwise it throws an error because, while rendering the TK tags,
you're not allowed to have one TK come more than once. That aside,
we don't want *each* occurrence having its own table column, do we?
2021-05-28 20:16:01 +05:30

241 lines
4.8 KiB
Svelte

<script>
import Importabular from "importabular"
import showdown from "showdown"
let converter = new showdown.Converter()
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])
}
}
// remove duplicates
tkList = [...new Set(tkList)]
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 && !!cookiePreviewText}
<h4 class="mt-3">Preview</h4>
<div class="cookie-preview">{@html converter.makeHtml(cookiePreviewText)}</div>
<button on:click={decrementPreviewRow}>&lt; Prev</button>
<button on:click={incrementPreviewRow}>Next &gt;</button>
{/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;
}
.cookie-preview {
text-align: left;
max-width: 640px;
margin: auto;
}
</style>