Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
886d417
feat(xpense): service skeleton, UI stub
gallayl Apr 4, 2020
79b9fcd
feat(xpense): skeleton vol 2.
gallayl Apr 4, 2020
1d6873a
Merge branch 'master' into feature/xpense
gallayl Apr 4, 2020
46d2b7c
chore(wrap-r-frontend):removed autocomplete, added datalist (wip)
gallayl Apr 5, 2020
83066c8
feat(common-components): Native autocomplete v0.1
gallayl Apr 5, 2020
c94fb46
feat(xpense):routes,replenishment
gallayl Apr 5, 2020
c15ddda
fix(xpense): frontend urls, replenish, etc...
gallayl Apr 5, 2020
fa469db
chore(package):updated dependencies
gallayl Apr 6, 2020
1ed19e9
feat(xpense-ui): refactored account context
gallayl Apr 6, 2020
e53a4f5
feat(xpense): Shopping V0.2
gallayl Apr 6, 2020
8328d73
chore(xpense ui): minor form fixes, added delete, added new row on sh…
gallayl Apr 6, 2020
c6de572
chore(package): updated dependencies
gallayl Apr 6, 2020
9b9a751
feat(nginx): added xpense to config
gallayl Apr 6, 2020
e909bf6
fix(wrap-r-frontend): xpense env vars
gallayl Apr 6, 2020
ea909cc
fix(wrap-r-frontend): typo in env.var
gallayl Apr 6, 2020
b8dfc2e
fix(config): more env var typos
gallayl Apr 6, 2020
47790ac
cleanup(wrap-r-frontend): simplified geting from env.vars
gallayl Apr 6, 2020
e93ab04
fix(xpense-ui):remove entry, update balance after shopping, update to…
gallayl Apr 7, 2020
f88453f
feat(xpense-ui): Account balance history chart v1
gallayl Apr 7, 2020
a96ef00
feat(xpense-ui): polished balance history graph
gallayl Apr 7, 2020
890e459
feat(xpense-ui):item,shopping,shop,replenishment detail stubs
gallayl Apr 7, 2020
758b3cb
feat(xpense-ui): get single entities, details page stubs
gallayl Apr 7, 2020
82c28e4
feat(project): moved data sets to utils, improved xpense authorization
gallayl Apr 7, 2020
0f305ad
feat(xpense-service): permanent replenishments and shoppings
gallayl Apr 7, 2020
216b848
chore(project): updated dependencies
gallayl Apr 7, 2020
a828020
feat(xpense-ui): improved header
gallayl Apr 7, 2020
bcc9e5b
feat(xpense-ui): redesigned account selector
gallayl Apr 7, 2020
2a09980
fix(xpense-ui): scrolls
gallayl Apr 7, 2020
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
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ module.exports = {
'cypress/no-unnecessary-waiting': 'error',
'cypress/assertion-before-screenshot': 'warn',
'default-case': 'error',
indent: 'off',
},
overrides: [
{
Expand Down
2 changes: 1 addition & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"id": "service",
"type": "pickString",
"description": "Select one service from above",
"options": ["wrap-r", "logg-r"]
"options": ["wrap-r", "logg-r", "xpense"]
}
]
}
2 changes: 1 addition & 1 deletion common/components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"description": "",
"private": true,
"scripts": {
"build": "tsc",
"build": "tsc --b",
"clean": "rimraf dist",
"test": "echo \"Error: no test specified\" && exit 1"
},
Expand Down
45 changes: 45 additions & 0 deletions common/components/src/autocomplete.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { Shade, createComponent } from '@furystack/shades'
import { v4 } from 'uuid'
import { Input, InputProps } from './input'

export const Autocomplete = Shade<
{ inputProps?: InputProps; suggestions: string[]; strict?: boolean; onchange: (value: string) => void },
{ dataListId: string }
>({
getInitialState: () => ({
dataListId: v4(),
}),
constructed: ({ getState, element }) => {
const { dataListId } = getState()
const input = element.querySelector('input')
if (input) {
input.setAttribute('list', dataListId)
}
},
shadowDomName: 'shade-autocomplete',
render: ({ props, getState }) => {
const { dataListId } = getState()
return (
<div>
<Input
{...props.inputProps}
onchange={(ev) => {
const { value } = ev.target as any
if (props.strict) {
if (!props.suggestions.includes(value)) {
;(ev.target as HTMLInputElement).setCustomValidity('Please select a valid entry!')
return
}
}
props.onchange(value)
}}
/>
<datalist id={dataListId}>
{props.suggestions.map((s) => (
<option value={s} />
))}
</datalist>
</div>
)
},
})
28 changes: 28 additions & 0 deletions common/components/src/fab.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { Shade, PartialElement, createComponent } from '@furystack/shades'

export const Fab = Shade<PartialElement<HTMLDivElement>>({
shadowDomName: 'shade-fab',
render: ({ props, children }) => {
return (
<div
{...props}
style={{
position: 'fixed',
bottom: '32px',
right: '32px',
background: 'gray',
width: '64px',
height: '64px',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
borderRadius: '50%',
boxShadow: '2px 2px 4px rgba(0,0,0,0.3)',
cursor: 'pointer',
...props.style,
}}>
{children}
</div>
)
},
})
2 changes: 2 additions & 0 deletions common/components/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
export * from './animations'
export * from './app-bar'
export * from './autocomplete'
export * from './avatar'
export * from './button'
export * from './data-grid'
export * from './fab'
export * from './grid'
export * from './input'
export * from './modal'
Expand Down
5 changes: 5 additions & 0 deletions common/components/src/input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { promisifyAnimation } from 'common-frontend-utils'
import { colors } from './styles'

export interface InputProps extends PartialElement<HTMLInputElement> {
onTextChange?: (text: string) => void
labelTitle?: string
multiLine?: false
}
Expand Down Expand Up @@ -47,6 +48,10 @@ export const Input = Shade<TextInputProps>({
</div>
) : (
<input
onchange={(ev) => {
props.onTextChange && props.onTextChange((ev.target as any).value)
props.onchange && (props.onchange as any)(ev)
}}
onfocus={() => {
if (!props.disabled) {
promisifyAnimation(
Expand Down
9 changes: 5 additions & 4 deletions common/components/src/modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,13 @@ export const Modal = Shade<{ isVisible: boolean; onClose?: () => void }>({
style={{
width: '100%',
height: '100%',
backgroundColor: 'rgba(128,128,128,0.03)',
position: 'absolute',
display: 'block',
// backgroundColor: 'rgba(128,128,128,0.03)',
position: 'fixed',
top: '0',
left: '0',
animation: 'show 100ms linear',
backdropFilter: 'contrast(0.3)brightness(0.2)blur(5px)',
// animation: 'show 100ms linear',
// backdropFilter: 'contrast(0.3)brightness(0.2)blur(5px)',
}}>
{children}
</div>
Expand Down
11 changes: 10 additions & 1 deletion common/components/src/tabs.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Shade, createComponent, PartialElement } from '@furystack/shades'
import { Shade, createComponent, PartialElement, LocationService } from '@furystack/shades'
import { promisifyAnimation } from 'common-frontend-utils/src'

export interface Tab {
Expand All @@ -18,6 +18,15 @@ export const Tabs = Shade<
>({
shadowDomName: 'shade-tabs',
getInitialState: ({ props }) => ({ activeIndex: props.activeTab || 0 }),
constructed: ({ injector, updateState }) => {
const locationSubscription = injector.getInstance(LocationService).onLocationChanged.subscribe((loc) => {
if (loc.hash && loc.hash.startsWith('#tab-')) {
const page = parseInt(loc.hash.replace('#tab-', ''), 10)
page && updateState({ activeIndex: page })
}
}, true)
return () => locationSubscription.dispose()
},
render: ({ props, getState, updateState }) => {
return (
<div style={{ width: '100%', height: '100%', display: 'flex', flexDirection: 'column', ...props.containerStyle }}>
Expand Down
14 changes: 13 additions & 1 deletion common/config/src/databases.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,24 @@ export const databases = {
usersCollection: 'users',
sessionStore: {
host: process.env.SESSION_STORE_HOST || process.env.REDIS_HOST || 'localhost',
port: process.env.SESSION_STORE_PORT || process.env.REDIS_PORT || '63790',
port: process.env.SESSION_STORE_PORT || process.env.REDIS_PORT || '6379',
},
},
logging: {
mongoUrl: process.env.MONGO_LOGGING_URL || process.env.MONGO_URL || 'mongodb://localhost:27017',
dbName: 'multiverse-logs',
logCollection: 'entries',
},
xpense: {
mongoUrl: process.env.MONGO_XPENSE_URL || process.env.MONGO_URL || 'mongodb://localhost:27017',
dbName: 'multiverse-xpense',
accounts: 'accounts',
items: 'items',
replenishments: 'replenishments',
shops: 'shops',
shoppings: 'private-xpenses',
},
standardOptions: {
useUnifiedTopology: true,
},
}
8 changes: 6 additions & 2 deletions common/config/src/sites.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,15 @@ export const sites = {
services: {
'wrap-r': {
internalPort: process.env.WRAPPR_SERVICE_INTERNAL_PORT || 9090,
externalPath: process.env.WRAPPR_SERVICE_EXTENRAL_URL || 'http://localhost:9090/api',
externalPath: process.env.WRAPPR_SERVICE_EXTERNAL_URL || 'http://localhost:9090/api',
},
'logg-r': {
internalPort: process.env.LOGGR_SERVICE_INTERNAL_PORT || 9091,
externalPath: process.env.LOGGR_SERVICE_EXTENAL_URL || 'http://localhost:9091/api',
externalPath: process.env.LOGGR_SERVICE_EXTERNAL_URL || 'http://localhost:9091/api',
},
xpense: {
internalPort: process.env.XPENSE_SERVICE_INTERNAL_PORT || 9092,
externalPath: process.env.XPENSE_SERVICE_EXTERNAL_URL || 'http://localhost:9092/api',
},
},
frontends: {
Expand Down
4 changes: 2 additions & 2 deletions common/frontend-utils/src/apis/logg-r-api.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { Injectable } from '@furystack/inject'
import { PathHelper } from '@furystack/utils'
import { LoggRApi } from 'common-models'
import { apis } from 'common-models'
import { createClient } from '@furystack/rest-client-fetch'
import { sites } from 'common-config'

@Injectable({ lifetime: 'singleton' })
export class LoggRApiService {
public call = createClient<LoggRApi>({
public call = createClient<apis.LoggRApi>({
endpointUrl: PathHelper.joinPaths(sites.services['logg-r'].externalPath, '/logg-r'),
requestInit: {
credentials: 'include',
Expand Down
4 changes: 2 additions & 2 deletions common/frontend-utils/src/apis/wrap-r-api.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { Injectable } from '@furystack/inject'
import { PathHelper } from '@furystack/utils'
import { WrapRApi } from 'common-models'
import { apis } from 'common-models'
import { createClient } from '@furystack/rest-client-fetch'
import { sites } from 'common-config'

@Injectable({ lifetime: 'singleton' })
export class WrapRApiService {
public call = createClient<WrapRApi>({
public call = createClient<apis.WrapRApi>({
endpointUrl: PathHelper.joinPaths(sites.services['wrap-r'].externalPath, '/wrap-r'),
requestInit: {
credentials: 'include',
Expand Down
15 changes: 15 additions & 0 deletions common/frontend-utils/src/apis/xpense-api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Injectable } from '@furystack/inject'
import { PathHelper } from '@furystack/utils'
import { apis } from 'common-models'
import { createClient } from '@furystack/rest-client-fetch'
import { sites } from 'common-config'

@Injectable({ lifetime: 'singleton' })
export class XpenseApiService {
public call = createClient<apis.XpenseApi>({
endpointUrl: PathHelper.joinPaths(sites.services.xpense.externalPath, '/xpense'),
requestInit: {
credentials: 'include',
},
})
}
1 change: 1 addition & 0 deletions common/frontend-utils/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export * from './apis/logg-r-api'
export * from './apis/wrap-r-api'
export * from './apis/xpense-api'
export * from './collection-service'
export * from './get-error-message'
export * from './service-list'
Expand Down
11 changes: 10 additions & 1 deletion common/frontend-utils/src/service-list.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { roles } from 'common-models/src'
import { roles } from 'common-models'

export interface ServiceDescription {
name: string
Expand All @@ -20,6 +20,15 @@ export const serviceList: ServiceDescription[] = [
showInDashboard: true,
requiredRoles: ['terms-accepted'],
},
{
name: 'Xpense',
icon: 'πŸ’°',
description: 'Manage accounts, incomes and expences',
showInMenu: true,
showInDashboard: true,
requiredRoles: ['terms-accepted'],
url: '/xpense',
},
{
name: 'Organizations',
icon: '🏒',
Expand Down
1 change: 1 addition & 0 deletions common/models/src/apis/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './session-api'
export * from './logg-r-api'
export * from './wrap-r-api'
export * from './xpense-api'
39 changes: 39 additions & 0 deletions common/models/src/apis/xpense-api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { RestApi, RequestAction } from '@furystack/rest'
import { Account, Shop, Item, Replenishment, Shopping } from '../xpense'

export interface XpenseApi extends RestApi {
GET: {
'/shops': RequestAction<{ result: Shop[] }>
'/items': RequestAction<{ result: Item[] }>
'/availableAccounts': RequestAction<{
result: Array<{
name: string
ownerType: Account['ownerType']
ownerName: Account['ownerName']
current: Account['current']
}>
}>
'/replenishments/:replenishmentId': RequestAction<{ urlParams: { replenishmentId: string }; result: Replenishment }>
'/shops/:shopId': RequestAction<{ urlParams: { shopId: string }; result: Shop }>
'/shopping/:shoppingId': RequestAction<{ urlParams: { shoppingId: string }; result: Shopping }>
'/:type/:owner/:accountName': RequestAction<{
result: Account
urlParams: { type: 'user' | 'organization'; owner: string; accountName: string }
}>
}
POST: {
'/accounts': RequestAction<{ result: Account; body: { name: string; description: string; icon: string } }>
'/shops': RequestAction<{ result: Shop; body: { name: string } }>
'/items': RequestAction<{ result: Item; body: { name: string; description: string; category?: string } }>
'/:type/:owner/:accountName/replenish': RequestAction<{
body: { amount: number; comment?: string }
urlParams: { type: 'user' | 'organization'; owner: string; accountName: string }
result: Replenishment
}>
'/:type/:owner/:accountName/shop': RequestAction<{
body: { shopName: string; entries: Array<{ itemName: string; amount: number; unitPrice: number }> }
urlParams: { type: 'user' | 'organization'; owner: string; accountName: string }
result: Shopping
}>
}
}
3 changes: 2 additions & 1 deletion common/models/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export * from './apis'
export * as apis from './apis'
export * from './github-account'
export * from './github-api-payload'
export * from './google-account'
Expand All @@ -7,3 +7,4 @@ export * from './log-entry'
export * from './profile'
export * from './session'
export * from './user'
export * as xpense from './xpense'
1 change: 1 addition & 0 deletions common/models/src/organization.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export class Organization {
_id!: string
name!: string
icon!: string
description!: string
/**
* The owner user name
Expand Down
18 changes: 18 additions & 0 deletions common/models/src/xpense/account.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
export class Account {
_id!: string
ownerType!: 'user' | 'organization'
ownerName!: string
name!: string
description!: string
icon!: string
history!: Array<{
balance: number
date: string
change: number
changePerCategory: Array<{ categoryName: string; amount: number }>
relatedEntry: { type: 'replenishment'; replenishmentId: string } | { type: 'shopping'; shoppingId: string }
}>
current!: number
createdBy!: string
creationDate!: string
}
5 changes: 5 additions & 0 deletions common/models/src/xpense/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export * from './account'
export * from './item'
export * from './replenishment'
export * from './shop'
export * from './shopping'
8 changes: 8 additions & 0 deletions common/models/src/xpense/item.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export class Item {
_id!: string
name!: string
description?: string
category?: string
creationDate!: string
createdBy!: string
}
7 changes: 7 additions & 0 deletions common/models/src/xpense/replenishment.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export class Replenishment {
_id!: string
createdBy!: string
accountId!: string
amount!: number
comment?: string
}
Loading