on master help sign in
Miscellaneous quality of life improvements to Grants (#739)

* rework top matter, add better navigation * remove ~sovmep-ripsum as assignee * add 'in progress' state * improve grants navigation adds CTAs to top of page, moves the ordering of sections around to something that feels more natural to me, and improves the filtering capabilities of the "find a grant" section * properly render the grantee * keep new styles * keep gitignore change * set tab on view proposals

commitd67be4196f9e5c29ab67dc056253fab4750f53c7 authorJosh Lehman <josh@urbit.org> dateWed 28 Jul 2021, 14:59 (5 years ago) parent01059c0
4 files changed+140−78
components/GrantPreview.js+3−2 content/grants/ra-page-tracking.md+1−1 pages/grants.js+132−73 pages/grants/[slug].js+4−2
components/GrantPreview.js+3−2
@@ -2,7 +2,8 @@ import classnames from "classnames";
22import Link from "next/link";
33
44export default function GrantPreview({ grant }) {
5− const isOpen = !grant.extra.completed && grant.extra.assignee === "";
5+ const isCompleted = grant.extra.completed;
6+ const isOpen = !isCompleted && grant.extra.assignee === "";
67 const type = grant.taxonomies.grant_type;
78
89 const className = classnames({
@@ -23,7 +24,7 @@ export default function GrantPreview({ grant }) {
2324 {grant.title}
2425 </h3>
2526 <div className={`bg-gray text-wall badge-sm ml-2`}>
26− {isOpen ? "Open" : "Completed"}
27+ {!isCompleted ? (isOpen ? "Open" : "In Progress") : "Completed"}
2728 </div>
2829 </div>
2930 <p className="mb-4">{grant.extra.description}</p>
content/grants/ra-page-tracking.md+1−1
@@ -9,7 +9,7 @@ image = ""
99description = "Improve Page Tracking"
1010reward = 2
1111mentor = "~silsyn-wathep"
12−assignee = "~sovmep-ripsum"
12+assignee = ""
1313completed = false
1414work_request_link = "https://airtable.com/shr4qt9t9kz7RaOIa?prefill_Grant+ID=A0039&prefill_Grant+Name=Runtime%20Apprenticeship%3A%20Improve%20Page%20Tracking"
1515+++
pages/grants.js+132−73
@@ -71,42 +71,59 @@ export default function Grants({
7171}) {
7272 const [activeTags, setTags] = useState([]);
7373 const [activeTypes, setTypes] = useState(types);
74+ const [includeOpen, setIncludeOpen] = useState(true);
7475 const [includeCompleted, setIncludeCompleted] = useState(false);
76+ const [includeInProgress, setIncludeInProgress] = useState(false);
7577 const [tab, setTab] = useState(0);
7678 const post = {
7779 title: "Grants",
7880 description: "Contribute to the Urbit project while earning address space.",
7981 };
8082
81− const postsByCompletion = posts.filter((post) => {
82− return includeCompleted
83− ? true
84− : !post.extra.completed && post.extra.assignee === "";
83+ const annotatedPosts = posts.map((post) => {
84+ if (post.extra.completed) {
85+ return { ...post, status: "completed" };
86+ } else if (post.extra.assignee && post.extra.assignee.length > 0) {
87+ return { ...post, status: "wip" };
88+ } else {
89+ return { ...post, status: "open" };
90+ }
8591 });
8692
87− const filteredPosts = postsByCompletion.filter((post) => {
93+ const byStatus = (post) => {
94+ return (
95+ (includeOpen ? post.status === "open" : false) ||
96+ (includeCompleted ? post.status === "completed" : false) ||
97+ (includeInProgress ? post.status === "wip" : false)
98+ );
99+ };
100+
101+ const postsByStatus = annotatedPosts.filter(byStatus);
102+
103+ const filteredPosts = annotatedPosts.filter((post) => {
88104 // Posts are returned if they match both the selected category and selected tags, or if the user has no category filters set.
89105 const hasCategory = post.taxonomies.grant_category.some((category) =>
90106 activeTags.includes(category)
91107 );
108+
92109 const noTagsSelected = activeTags.length === 0;
93110 const hasType = post.taxonomies.grant_type.some((type) =>
94111 activeTypes.includes(type)
95112 );
96113
97− return (hasCategory || noTagsSelected) && hasType;
114+ return (hasCategory || noTagsSelected) && byStatus(post) && hasType;
98115 });
99116
100− const allCount = postsByCompletion.length;
117+ const allCount = postsByStatus.length;
101118
102119 const counts = {
103− Bounty: postsByCompletion.filter((post) =>
120+ Bounty: postsByStatus.filter((post) =>
104121 post.taxonomies.grant_type.includes("Bounty")
105122 ).length,
106− Apprenticeship: postsByCompletion.filter((post) =>
123+ Apprenticeship: postsByStatus.filter((post) =>
107124 post.taxonomies.grant_type.includes("Apprenticeship")
108125 ).length,
109− Proposal: postsByCompletion.filter((post) =>
126+ Proposal: postsByStatus.filter((post) =>
110127 post.taxonomies.grant_type.includes("Proposal")
111128 ).length,
112129 };
@@ -123,7 +140,7 @@ export default function Grants({
123140 // Heading and introduction
124141 }
125142 <Section wide short>
126− <div className="flex flex-column justify-between">
143+ <div className="flex flex-column justify-between pb-16">
127144 <div>
128145 <h1 className="pb-16">Grants</h1>
129146 <p className="mb-8">
@@ -137,7 +154,23 @@ export default function Grants({
137154 at urbit.org, Tlon developers, and community mentors.
138155 </p>
139156 </div>
140− <TableOfContents staticPosition noh3s />
157+ </div>
158+ <div className="flex flex-wrap">
159+ <Link href="#find-a-grant">
160+ <button className="button-lg bg-green text-white mr-2">
161+ View Grants
162+ </button>
163+ </Link>
164+ <Link href="#proposals">
165+ <button className="button-lg bg-blue text-white mr-2">
166+ Submit a Proposal
167+ </button>
168+ </Link>
169+ <Link href="#gifts">
170+ <a className="button-lg bg-ultraDeepWall text-white mr-2">
171+ Recent Gifts
172+ </a>
173+ </Link>
141174 </div>
142175 </Section>
143176 {
@@ -171,12 +204,79 @@ export default function Grants({
171204 })}
172205 </div>
173206 </Section>
174− {
175− // Find a Grant
176− }
207+ {/* Submit a proposal */}
208+ <Section wide>
209+ <h2 className="mb-16" id="proposals">
210+ Proposals
211+ </h2>
212+ <p className="mb-8">
213+ Contributors are also welcome to have their personal projects
214+ considered as a proposal. If you'd like to propose a project for the
215+ grants program, first review our
216+ <a href="/grant-submission-guide">submission guide</a>, and feel
217+ free to{" "}
218+ <a href="https://airtable.com/shrCi54rEDxgSZr3z">
219+ submit your proposal
220+ </a>
221+ .
222+ </p>
223+
224+ <Link href="#find-a-grant">
225+ <button
226+ className="button-lg bg-blue text-white mr-2"
227+ onClick={() => {
228+ setIncludeInProgress(true);
229+ setIncludeCompleted(true);
230+ setTab(1);
231+ setTypes(["Proposal"]);
232+ }}
233+ >
234+ View Proposals
235+ </button>
236+ </Link>
237+ </Section>
238+ {/* Gift Grants */}
239+ <Section wide>
240+ <div className="pb-16">
241+ <h2 className="pb-16" id="gifts">
242+ Gifts
243+ </h2>
244+ <p className="mb-8">
245+ Gifts are given post-facto for exceptional contributions.
246+ </p>
247+ {/* Uncomment once people added to content/gifts folder. */}
248+ {/* {gifts.map((e) => {
249+ return (
250+ <div className="bg-wall rounded-xl p-4 my-8 flex justify-between">
251+ <p className="font-semibold">
252+ {e.name}
253+ </p>
254+ <p>{e.planet}</p>
255+ <p>{e.date}</p>
256+ <a className="type-p" href={e.link}>Link</a>
257+ </div>
258+ )
259+ })} */}
260+ <div className="flex flex-wrap">
261+ <PostPreview
262+ post={giftPosts[0]}
263+ className={`w-full md:w-1/2 pr-0 pb-8 md:pr-4`}
264+ key={giftPosts[0].slug}
265+ section={giftPosts[0].section}
266+ />
267+ <PostPreview
268+ post={giftPosts[1]}
269+ className={`w-full md:w-1/2 pl-0 pb-8 md:pl-4`}
270+ key={giftPosts[1].slug}
271+ section={giftPosts[1].section}
272+ />
273+ </div>
274+ </div>
275+ </Section>
276+ {/* Find a Grant */}
177277 <Section wide>
178278 <h2 id="find-a-grant" className="pb-8">
179− Find A Grant
279+ Find a Grant
180280 </h2>
181281 <h5 className="text-black font-semibold my-2">Work Programs</h5>
182282 <div className="flex flex-wrap items-center pb-2">
@@ -233,6 +333,13 @@ export default function Grants({
233333 </div>
234334 {
235335 <div className="pb-8 flex items-center">
336+ <button
337+ className="mr-4 badge-sm bg-black text-white"
338+ onClick={() => setIncludeOpen(!includeOpen)}
339+ >
340+ {includeOpen ? "Exclude Open" : "Include Open"}
341+ </button>
342+
236343 <button
237344 className="mr-4 badge-sm bg-black text-white"
238345 onClick={() => setIncludeCompleted(!includeCompleted)}
@@ -240,6 +347,15 @@ export default function Grants({
240347 {includeCompleted ? "Exclude Completed" : "Include Completed"}
241348 </button>
242349
350+ <button
351+ className="mr-4 badge-sm bg-black text-white"
352+ onClick={() => setIncludeInProgress(!includeInProgress)}
353+ >
354+ {includeInProgress
355+ ? "Exclude In Progress"
356+ : "Include In Progress"}
357+ </button>
358+
243359 <h4>
244360 Showing {filteredPosts.length} grant
245361 {filteredPosts.length === 1 ? "" : "s"}
@@ -250,63 +366,6 @@ export default function Grants({
250366 return <GrantPreview grant={post} />;
251367 })}
252368 </Section>
253− {/* Submit a proposal */}
254− <Section wide>
255− <h2 className="mb-16" id="proposals">
256− Proposals
257− </h2>
258− <p className="mb-8">
259− Contributors are also welcome to have their personal projects
260− considered as a proposal. If you'd like to propose a project for the
261− grants program, first review our
262− <a href="/grant-submission-guide">submission guide</a>, and feel
263− free to{" "}
264− <a href="https://airtable.com/shrCi54rEDxgSZr3z">
265− submit your proposal
266− </a>
267− .
268− </p>
269− </Section>
270− {
271− // Gift Grants
272− }
273− <Section wide>
274− <div className="pb-16">
275− <h2 className="pb-16" id="gifts">
276− Gifts
277− </h2>
278− <p className="mb-8">
279− Gifts are given post-facto for exceptional contributions.
280− </p>
281− {/* Uncomment once people added to content/gifts folder. */}
282− {/* {gifts.map((e) => {
283− return (
284− <div className="bg-wall rounded-xl p-4 my-8 flex justify-between">
285− <p className="font-semibold">
286− {e.name}
287− </p>
288− <p>{e.planet}</p>
289− <p>{e.date}</p>
290− <a className="type-p" href={e.link}>Link</a>
291− </div>
292− )
293− })} */}
294− <div className="flex flex-wrap">
295− <PostPreview
296− post={giftPosts[0]}
297− className={`w-full md:w-1/2 pr-0 pb-8 md:pr-4`}
298− key={giftPosts[0].slug}
299− section={giftPosts[0].section}
300− />
301− <PostPreview
302− post={giftPosts[1]}
303− className={`w-full md:w-1/2 pl-0 pb-8 md:pl-4`}
304− key={giftPosts[1].slug}
305− section={giftPosts[1].section}
306− />
307− </div>
308− </div>
309− </Section>
310369 </SingleColumn>
311370 <Footer />
312371 </Container>
pages/grants/[slug].js+4−2
@@ -37,8 +37,10 @@ export default function Grant({ post, markdown, search, similarGrants }) {
3737 <Header search={search} />
3838 <Section narrow short>
3939 <h1>{post.title}</h1>
40− {post.extra.author ? (
41− <div className="type-ui text-gray mt-4">{post.extra.author}</div>
40+ {post.extra.assignee ? (
41+ <div className="type-ui text-gray mt-4">
42+ Grantee: {post.extra.assignee}
43+ </div>
4244 ) : null}
4345 {post.extra.ship ? (
4446 <div className="type-ui text-gray font-mono">{post.extra.ship}</div>