Skip to content

Commit

Permalink
Add file submission
Browse files Browse the repository at this point in the history
  • Loading branch information
Aaron-9900 committed Mar 31, 2021
1 parent f43906b commit e0f538f
Show file tree
Hide file tree
Showing 17 changed files with 520 additions and 44 deletions.
4 changes: 4 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import Login from "./screens/login"
import Register from "./screens/register"
import { PrivateRoute } from "./navigation/private-route"
import CreateProposal from "./screens/create-proposal"
import ProposalDetail from "./screens/proposal-detail"

const App = observer(function App() {
const [rootStore, setRootStore] = useState<RootStore | null>(null)
Expand All @@ -30,6 +31,9 @@ const App = observer(function App() {
<PrivateRoute path="/proposal/create">
<CreateProposal />
</PrivateRoute>
<PrivateRoute path="/proposal/:id">
<ProposalDetail />
</PrivateRoute>
<Route path="/login">
<Login></Login>
</Route>
Expand Down
29 changes: 29 additions & 0 deletions src/components/avatar-with-title/avatar-with-title.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React from "react"
import { Row, Col, Avatar } from "antd"
import styled from "styled-components"
import Title from "antd/lib/typography/Title"
import { color } from "../../utils/colors"
const StyledUsernameWrapper = styled.div`
display: flex;
margin-bottom: 3vh;
`
const StyledAvatar = styled(Avatar)`
margin-right: 10px;
`
interface AvatarProps {
value: string
size: 2 | 5 | 1 | 3 | 4 | undefined
}
export const AvatarWithTitle = (props: AvatarProps): JSX.Element => {
const { value, size } = props
return (
<Row>
<Col offset={2} span={18}>
<StyledUsernameWrapper>
<StyledAvatar style={{ backgroundColor: color(value) }}>{value[0]}</StyledAvatar>
<Title level={size}>{value}</Title>
</StyledUsernameWrapper>
</Col>
</Row>
)
}
2 changes: 1 addition & 1 deletion src/models/auth-model/auth-model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export const AuthModel = types
.views((self) => {
return {
get isLogged(): boolean {
return !!self.username
return !!self.username && self.environment.api.hasCredentials()
},
}
})
Expand Down
55 changes: 55 additions & 0 deletions src/models/extensions/with-status.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { observable, IObservableValue } from "mobx"

export type StatusType = "idle" | "pending" | "done" | "error"

/**
* Adds a status field to the model often for tracking api access.
*
* This property is a string which can be observed, but will not
* participate in any serialization.
*
* Use this to extend your models:
*
* ```ts
* types.model("MyModel")
* .props({})
* .actions(self => ({}))
* .extend(withStatus) // <--- time to shine baby!!!
* ```
*
* This will give you these 3 options:
*
* .status // returns a string
* .status = "done" // change the status directly
* .setStatus("done") // change the status and trigger an mst action
*/
export const withStatus = () => {
/**
* The observable backing store for the status field.
*/
const status: IObservableValue<string> = observable.box("idle")

return {
views: {
// a getter
get status() {
return status.get() as StatusType
},
// as setter
set status(value: StatusType) {
status.set(value)
},
},
actions: {
/**
* Set the status to something new.
*
* @param value The new status.
*/
setStatus(value: StatusType) {
status.set(value)
},
},
}
}
66 changes: 66 additions & 0 deletions src/models/proposals-model/proposal-detail.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { applySnapshot, flow, Instance, SnapshotOut, types } from "mobx-state-tree"
import { GetSignedUrl, GetSingleProposal, PutFile } from "../../services/api-types"
import { withEnvironment } from "../extensions/with-environment"
import { withStatus } from "../extensions/with-status"
import { UserModel } from "../user-model/user-model"
import { ProposalModel } from "./proposal-model"

export const ProposalDetailModel = types
.model("ProposalDetailModel")
.props({
proposal: types.maybeNull(ProposalModel),
})
.extend(withEnvironment)
.extend(withStatus)
.actions((self) => {
return {
getProposal: flow(function* (id: string) {
self.setStatus("pending")
try {
const response: GetSingleProposal = yield self.environment.api.getProposal(id)
if (response.kind !== "ok") {
throw response
}

self.proposal = response.proposal as any
self.setStatus("idle")
} catch (err) {
self.setStatus("error")
}
}),
putFile: flow(function* (fileName: string, file: File, progress: (event: any) => void) {
self.setStatus("pending")
try {
const response: PutFile = yield self.environment.api.submitFile(fileName, file, progress)
if (response.kind !== "ok") {
throw response
}
self.setStatus("idle")
return response
} catch (err) {
console.log(err)
self.setStatus("error")
}
}),
getSignedUrl: flow(function* (fileName: string) {
self.setStatus("pending")
try {
const response: GetSignedUrl = yield self.environment.api.getSignedUrl(fileName)
console.log(response)
if (response.kind !== "ok") {
throw response
}
self.setStatus("idle")
return response.url
} catch (err) {
console.log(err)
self.setStatus("error")
}
}),
}
})

type ProposalDetailModelType = Instance<typeof ProposalDetailModel>
export interface ProposalDetailModel extends ProposalDetailModelType {}
type ProposalDetailModelSnapshotType = SnapshotOut<typeof ProposalDetailModel>
export interface ProposalDetailModelSnapshot extends ProposalDetailModelSnapshotType {}
2 changes: 2 additions & 0 deletions src/models/proposals-model/proposal-model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ export const ProposalModel = types
description: "",
limit: 0,
user: UserModel,
type: types.string,
rate: 0,
})
.actions((self) => {
return {}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,30 +1,32 @@
import { applySnapshot, flow, Instance, SnapshotOut, types } from "mobx-state-tree"
import { GetProposals, PostProposal } from "../../services/api-types"
import { GetProposals, GetProposalTypes, PostProposal } from "../../services/api-types"
import { withEnvironment } from "../extensions/with-environment"
import { withStatus } from "../extensions/with-status"
import { ProposalModel } from "./proposal-model"

export const ProposalsModelStore = types
.model("ProposalsModelStore")
.props({
proposals: types.array(ProposalModel),
loading: false,
})
.extend(withEnvironment)
.extend(withStatus)
.actions((self) => {
return {
getProposals: flow(function* (from: number, to: number) {
try {
self.loading = true
self.setStatus("pending")
const response: GetProposals = yield self.environment.api.getProposals(from, to)
self.loading = false
self.setStatus("done")
if (response.kind === "ok") {
const proposals = response.proposals
applySnapshot(self.proposals, proposals as any)
} else {
throw response
}
} catch (err) {
self.loading = false
self.setStatus("error")

throw err
}
}),
Expand All @@ -33,22 +35,42 @@ export const ProposalsModelStore = types
description: string,
rate: number,
limit: number,
type: string,
) {
try {
self.loading = true
self.setStatus("pending")
const response: PostProposal = yield self.environment.api.postProposal(
name,
description,
rate,
limit,
type,
)
self.loading = false
self.setStatus("done")
if (response.kind === "ok") {
self.proposals.push(response.proposal)
return true
} else {
throw response
}
} catch (err) {}
} catch (err) {
console.log(err)
self.setStatus("error")
}
}),
getProposalTypes: flow(function* () {
//
try {
const response: GetProposalTypes = yield self.environment.api.getProposalTypes()
if (response.kind === "ok") {
const types = response.types
return types
} else {
throw response
}
} catch (err) {
self.setStatus("error")
}
}),
}
})
Expand Down
2 changes: 2 additions & 0 deletions src/models/root-store/root-store.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Instance, SnapshotOut, types } from "mobx-state-tree"
import { AuthModel } from "../auth-model/auth-model"
import { ProposalDetailModel } from "../proposals-model/proposal-detail"
import { ProposalsModelStore } from "../proposals-model/proposals-model-store"

/**
Expand All @@ -8,6 +9,7 @@ import { ProposalsModelStore } from "../proposals-model/proposals-model-store"
export const RootStoreModel = types.model("RootStore").props({
authStore: types.optional(AuthModel, {}),
proposalsStore: types.optional(ProposalsModelStore, {}),
proposalDetailStore: types.optional(ProposalDetailModel, {}),
})

/**
Expand Down
Loading

0 comments on commit e0f538f

Please sign in to comment.