Skip to content

Commit

Permalink
Show Basket Time to Deletion (#106)
Browse files Browse the repository at this point in the history
Users should be able to see what date their baskets expire on.
Currently, Pantry will refresh the TTL of a basket after each CRUD
operation. Stale baskets will expire after a few days. We should at
a minimum display the TTL of each basket on the dashboard so users
can view which baskets are stale.

* Introduce a TTL function to the dataStore
* Change the response type of Account.getBlocks()
* Add FontAwesome to the frontend
* Display the expiry date (TTL) of each basket beside it's name

Resolves #79
  • Loading branch information
imRohan committed Sep 23, 2021
1 parent 2667de3 commit f369568
Show file tree
Hide file tree
Showing 14 changed files with 1,307 additions and 1,419 deletions.
2 changes: 1 addition & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ module.exports = {
"@typescript-eslint/no-empty-function": "warn",
"@typescript-eslint/no-empty-interface": "error",
"@typescript-eslint/no-explicit-any": "warn",
"@typescript-eslint/no-unsafe-assignment": "warn",
"@typescript-eslint/no-unsafe-assignment": "off",
"@typescript-eslint/no-unsafe-call": "off",
"@typescript-eslint/no-unsafe-member-access": "off",
"@typescript-eslint/no-unsafe-return": "warn",
Expand Down
26 changes: 26 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@
"webpack-merge": "^4.1.3"
},
"dependencies": {
"@fortawesome/fontawesome-svg-core": "^1.2.36",
"@fortawesome/free-solid-svg-icons": "^5.15.4",
"@fortawesome/vue-fontawesome": "^2.0.2",
"@sendgrid/mail": "^7.1.1",
"airtable": "^0.8.1",
"axios": "^0.21.2",
Expand Down
5 changes: 5 additions & 0 deletions src/app/components/landingRight.ts
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,11 @@ const landingRight = {

return _positiveStatus ? _positiveMessage : _negativeMessage
},
getDateOfDeletion(ttl: number): string {
const _currentDate = new Date()
_currentDate.setSeconds(ttl)
return _currentDate.toISOString().split('T')[0]
},
},
mounted() {
this.fetchURLParams()
Expand Down
7 changes: 7 additions & 0 deletions src/app/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
// External Files
import { library } from '@fortawesome/fontawesome-svg-core'
import { faEye, faEyeSlash, faClipboard } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
const vue = require('vue')
const vueClipboard = require('vue-clipboard2')

// Vue Setup
vue.use(vueClipboard)
vue.component('font-awesome-icon', FontAwesomeIcon)
library.add(faClipboard)
library.add(faEye)
library.add(faEyeSlash)

// CSS
require('./scss/main.scss')
Expand Down
5 changes: 1 addition & 4 deletions src/app/scss/_text.scss
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,7 @@ a:any-link {
float: right;
color: $secondary-color;
cursor: pointer;
margin: 0 3px;
&--no-float {
float: inherit;
}
margin: 0 5px;
}
&--light {
color: $secondary-color;
Expand Down
24 changes: 17 additions & 7 deletions src/app/templates/landingRight.html
Original file line number Diff line number Diff line change
Expand Up @@ -161,16 +161,26 @@ <h2>
<template v-if="pantry.data.baskets && pantry.data.baskets.length !== 0">
<div class="basket__container">
<ul>
<template v-for="basketName in pantry.data.baskets">
<template v-for="{ name, ttl } in pantry.data.baskets">
<li class="text__container">
{{ basketName }}
<span class="text__button" @click="toggleBasket(basketName)">
{{ activeBasket === basketName ? 'Hide' : 'Show' }} Contents
{{ name }} -
<small>
Expiry Date: {{ getDateOfDeletion(ttl) }}
</small>
<span class="text__button" title="View Contents"
@click="toggleBasket(name)">
<template v-if="activeBasket === name">
<font-awesome-icon icon="eye-slash" />
</template>
<template v-else>
<font-awesome-icon icon="eye" />
</template>
</span>
<span class="text__button text__button--no-float" @click="copyBasketLink(basketName)">
Copy Link
<span class="text__button" title="Copy Direct Link"
@click="copyBasketLink(name)">
<font-awesome-icon icon="clipboard" />
</span>
<template v-if="activeBasket === basketName">
<template v-if="activeBasket === name">
<div class="basket__payload-container">
<json-view
:deep="1"
Expand Down
7 changes: 4 additions & 3 deletions src/controllers/account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,10 @@ class AccountController {
const _blocks = await _account.getBlocks()

logger.info(`Deleting account: ${uuid}`)
for (const _blockName of _blocks) {
logger.info(`Deleting block ${_blockName} in account: ${uuid}`)
const _block = await Block.get(uuid, _blockName)
for (const _item of _blocks) {
const { name } = _item
logger.info(`Deleting block ${name} in account: ${uuid}`)
const _block = await Block.get(uuid, name)
await _block.delete()
}
await _account.delete()
Expand Down
4 changes: 3 additions & 1 deletion src/interfaces/account.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { IBlockInfo } from './block'

export interface IAccountParams {
name: string,
description: string,
Expand Down Expand Up @@ -25,6 +27,6 @@ export interface IAccountPrivate extends IAccountBase {
}

export interface IAccountPublic extends IAccountBase {
baskets: string[],
baskets: IBlockInfo[],
percentFull: number,
}
5 changes: 5 additions & 0 deletions src/interfaces/block.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,8 @@ export interface IBlock {
name: string,
payload: any,
}

export interface IBlockInfo {
name: string,
ttl: number,
}
16 changes: 10 additions & 6 deletions src/models/account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import * as mailer from '../services/mailer'

// Interfaces
import { IAccountPrivate, IAccountPublic, IAccountUpdateParams } from '../interfaces/account'
import { IBlockInfo } from '../interfaces/block'

const KEYS_PER_SCAN_ITERATION = 1_000_000

Expand Down Expand Up @@ -157,13 +158,16 @@ class Account {
await this.store()
}

public async getBlocks(): Promise<string[]> {
public async getBlocks(): Promise<IBlockInfo[]> {
const _accountKey = Account.generateRedisKey(this.uuid)
const _blocks = await dataStore.find(`${_accountKey}::block:*`)

const _blocksSanitized = _blocks.map((block) => block.split(':')[4])

return _blocksSanitized
const _blockKeys = await dataStore.find(`${_accountKey}::block:*`)
const _blocks: IBlockInfo[] = await Promise.all(_blockKeys.map(async (key) => {
const _ttl = await dataStore.ttl(key)
const _sanitizedName = key.split(':')[4]
return({name: _sanitizedName, ttl: _ttl})
}))

return(_blocks)
}

public async saveError(message: string): Promise<void> {
Expand Down
1 change: 1 addition & 0 deletions src/services/__mocks__/dataStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const dataStore = {
find: jest.fn(async () => { }),
scan: jest.fn(async () => { }),
ping: jest.fn(async () => { }),
ttl: jest.fn(async () => { }),
}

export = dataStore
14 changes: 14 additions & 0 deletions src/services/dataStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,3 +133,17 @@ export async function ping(): Promise<boolean> {
return false
}
}

export async function ttl(key: string): Promise<number> {
try {
const _redisClient = redis.createClient()
const _ttl = promisify(_redisClient.ttl).bind(_redisClient)
const _response = await _ttl(key)
_redisClient.quit()

return _response
} catch (error) {
logger.error(`Error when fetching ttl: ${error.message}`)
return -1
}
}
Loading

0 comments on commit f369568

Please sign in to comment.