Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions .github/workflows/storybook-airtable-app.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# name of our action
name: 'Deploy StorybookJS: Airtable apps'
# the event that will trigger the action
on:
push:
paths:
- 'airtable-apps/send_email/**'
- '.github/workflows/storybook-airtable-app.yml'

# what the action will do
jobs:
deploy:
# the operating system it will run on
runs-on: ubuntu-latest
# the list of steps that the action will go through
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0

# Move all react files to root (including hidden dotfiles)
- run: |
shopt -s dotglob
git mv airtable-apps/send_email/* ./ -fk

- run: npm install

- uses: chromaui/action@v1
# options required to the GitHub chromatic action
with:
projectToken: ayhiuop76lu
token: ${{ secrets.GITHUB_TOKEN }}
31 changes: 31 additions & 0 deletions .github/workflows/storybook-links.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: Link to Storybooks
on: push

jobs:
add-links:
runs-on: ubuntu-latest
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CI_COMMIT_ID: ${{ github.event.pull_request.head.sha || github.sha }}
CI_REPO_NAME: ${{ github.repository }}

steps:
# See: https://stackoverflow.com/a/58035262/504018
- name: Extract branch name
shell: bash
run: echo "##[set-output name=branch;]$(echo ${GITHUB_REF#refs/heads/})"
id: extract-branch

- name: Use Node.js
uses: actions/[email protected]
with:
node-version: 14.4.0

# See: https://github.com/taskworld/commit-status
- name: Install commit-status CLI tool
run: npm install -g commit-status

- name: Set commit status messages and success states
run: |
commit-status success "Storybook: React UI" "Available after deploy" "https://${{ steps.extract-branch.outputs.branch }}--5f9b7272e5c4a70022388106.chromatic.com/"
commit-status success "Storybook: Airtable app - Email" "Available after deploy" "https://${{ steps.extract-branch.outputs.branch }}--5fb3fd84c168100021f7aa64.chromatic.com"
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
# name of our action
name: 'Push StorybookJS to Chromatic'
name: 'Deploy StorybookJS: React UI'
# the event that will trigger the action
on: push
on:
push:
paths:
- 'react-ui/**'
- '.github/workflows/storybook-react-ui.yml'

# what the action will do
jobs:
build-push:
deploy:
# the operating system it will run on
runs-on: ubuntu-latest
# the list of steps that the action will go through
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0

# Move all react files to root (including hidden dotfiles)
- run: |
Expand Down
9 changes: 9 additions & 0 deletions airtable-apps/send_email/.storybook/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module.exports = {
"stories": [
"../frontend/**/*.stories.@(js|jsx|ts|tsx)"
],
"addons": [
"@storybook/addon-links",
"@storybook/addon-essentials"
]
}
4 changes: 4 additions & 0 deletions airtable-apps/send_email/.storybook/preview.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

export const parameters = {
actions: { argTypesRegex: "^on[A-Z].*" },
}
5 changes: 5 additions & 0 deletions airtable-apps/send_email/frontend/components/Alert.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React, { useState, useEffect } from 'react'
import PropTypes from 'prop-types'
import { Text, Button, Box, colors } from '@airtable/blocks/ui'

const Alert = ({ alert, onClose }) => {
Expand Down Expand Up @@ -31,5 +32,9 @@ const Alert = ({ alert, onClose }) => {
</Box>
)
}
Alert.propTypes = {
alert: PropTypes.string.isRequired,
onClose: PropTypes.func
}

export default Alert
14 changes: 14 additions & 0 deletions airtable-apps/send_email/frontend/components/Alert.stories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import React from 'react'
import Alert from './Alert'

export default {
component: Alert,
title: 'Airtable Apps/Alert'
}

const Template = args => <Alert {...args} />

export const Default = Template.bind({})
Default.args = {
alert: 'Some message',
}
12 changes: 12 additions & 0 deletions airtable-apps/send_email/frontend/components/HintedLink.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { Link, Tooltip } from '@airtable/blocks/ui'
import React from 'react'

const HintedLink = ({ hint = '', href = '#', icon, children }) => {
return (
<Tooltip content={hint} placementY={Tooltip.placements.BOTTOM} placementX={Tooltip.placements.CENTER}>
<Link target="_blank" href={href} icon={icon} marginLeft={2}>{children}</Link>
</Tooltip>
)
}

export default HintedLink
17 changes: 17 additions & 0 deletions airtable-apps/send_email/frontend/components/HintedLink.stories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import React from 'react'
import HintedLink from './HintedLink'

export default {
component: HintedLink,
title: 'Airtable Apps/HintedLink'
}

const Template = args => <HintedLink {...args} />

export const Default = Template.bind({})
Default.args = {
hint: 'Some hint about what to expect',
children: 'Some Link Text',
href: 'https://example.com',
icon: 'star'
}
54 changes: 54 additions & 0 deletions airtable-apps/send_email/frontend/components/SendInfoBox.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { Box, Icon, Text } from '@airtable/blocks/ui'
import React from 'react'
import HintedLink from './HintedLink'

const SendInfoBox = ({ tableData = [], templateVars = [], templateEditLink = '#', templatePreviewLink = '#' }) => {
const totalCount = tableData.length
const emailMissingCount = tableData.filter((row) => !row.email).length

return (
<Box
border="thick"
borderRadius="large"
padding={2}
backgroundColor="lightGray1"
>
<Box marginBottom={2}>
<Text>
To be sent:
{' '}
<span style={{fontWeight: 700}}>{totalCount - emailMissingCount}</span> rows
{emailMissingCount > 0 &&
<span>{', '}{emailMissingCount} missing email(s)</span>
}
</Text>
</Box>
<Box marginBottom={2}>
<Text marginBottom={2}>
Selected template:
<HintedLink hint="Redirects to Mailjet. Login required." icon="edit" href={templateEditLink}>Edit</HintedLink>
<HintedLink hint="Redirects to Mailjet. Login required." icon="show1" href={templatePreviewLink}>View/Test</HintedLink>
</Text>
</Box>
<Text size="large" marginBottom={2}>Template variables:</Text>
{templateVars.length === 0 && <Text textColor="gray" marginLeft={4}>(none)</Text>}
{templateVars.map((v, i) => (
v.isColMissing
? <Box display="flex">
<Icon name="warning" size={16} fillColor="IndianRed" marginX={2} />
<Text style={{ textShadow: '-0.04ex 0 #000, 0.04ex 0 #000' }} marginRight={1}>{v.name}</Text>
<Text textColor="gray">(missing column)</Text>
</Box>
: <Box display="flex">
<Icon name="check" size={16} fillColor="gray" marginX={2} />
<Text textColor="gray">{v.name}</Text>
</Box>
))}
</Box>
)
}

SendInfoBox.propTypes = {
}

export default SendInfoBox
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import React from 'react'
import SendInfoBox from './SendInfoBox'

export default {
component: SendInfoBox,
title: 'Airtable Apps/SendInfoBox'
}

const Template = args => <SendInfoBox {...args} />

export const Default = Template.bind({})
Default.args = {
tableData: [
{email: '[email protected]', first_name: 'Jane', program_name: 'Program A'},
{email: '[email protected]', first_name: 'Maria', program_name: 'Program B'},
{email: '[email protected]', first_name: 'John', program_name: 'Program A'},
],
templateVars: [
{name: 'email', default: '', isColMissing: false},
{name: 'first_name', default: 'applicant', isColMissing: false},
{name: 'program_name', default: 'StART', isColMissing: false},
],
templateEditLink: 'https://app.mailjet.com/template/1743481/build',
templatePreviewLink: 'https://app.mailjet.com/template/1743612/preview',
}

export const ViewMissingColumn = Template.bind({})
ViewMissingColumn.args = {
...Default.args,
templateVars: [
Default.args.templateVars[0],
Default.args.templateVars[1],
Object.assign({}, Default.args.templateVars[2], {isColMissing: true}),
]
}

export const RowsMissingEmail = Template.bind({})
RowsMissingEmail.args = {
...Default.args,
tableData: [
Default.args.tableData[0],
Default.args.tableData[1],
Object.assign({}, Default.args.tableData[2], {email: null}),
]
}

export const NoTemplateVariables = Template.bind({})
NoTemplateVariables.args = {
...Default.args,
templateVars: []
}

function range(start, end) {
return Array.from({ length: end - start + 1 }, (_, i) => i)
}

var manyRows = range(0, 9999).map(n => ({email: `user${n}@example.com`, first_name: `Jane ${n}`}))
manyRows[10].email = null

export const ManyRecipients = Template.bind({})
ManyRecipients.args = {
...Default.args,
tableData: manyRows
}
Loading