70 | );
71 | }
72 |
73 | export default App;
74 |
--------------------------------------------------------------------------------
/functions/utils/astraRestClient.js:
--------------------------------------------------------------------------------
1 | const { createClient}= require("@astrajs/rest")
2 | const chalk = require('chalk')
3 | let astraRestClient = null;
4 |
5 | const requestWithRetry = async (url, client) => {
6 | const MAX_RETRIES = 20;
7 | for (let i = 1; i <= MAX_RETRIES; i++) {
8 | try {
9 | let response = await client.get(url);
10 | return response
11 | } catch(e) {
12 | const timeout = 500 * i * 10;
13 | console.log(chalk.blue(' ... waiting', timeout, 'ms'));
14 | await wait(timeout);
15 | }
16 | }
17 | }
18 |
19 | function wait(timeout) {
20 | return new Promise((resolve) => {
21 | setTimeout(() => {
22 | resolve();
23 | }, timeout);
24 | });
25 | }
26 |
27 | const getAstraRestClient = async () => {
28 | if (astraRestClient === null) {
29 | astraRestClient = await createClient(
30 | {
31 | astraDatabaseId: process.env.ASTRA_DB_ID,
32 | astraDatabaseRegion: process.env.ASTRA_DB_REGION,
33 | applicationToken: process.env.ASTRA_DB_APPLICATION_TOKEN,
34 | debug: true
35 | },
36 | 30000
37 | );
38 |
39 | // Check for the "rest" table. If it doesn't exist create it dynamically.
40 | let tables = await astraRestClient.get('/api/rest/v2/schemas/keyspaces/todos/tables')
41 | let results = tables.data.filter(entry => entry.name === "rest");
42 | if (!results.length) {
43 | await createTable("rest")
44 | }
45 | }
46 | return astraRestClient;
47 | };
48 |
49 | async function createTable(name) {
50 | let response = await astraRestClient.post('/api/rest/v2/schemas/keyspaces/todos/tables',
51 | {
52 | "name": "rest",
53 | "ifNotExists": true,
54 | "columnDefinitions": [
55 | {
56 | "name": "id",
57 | "typeDefinition": "uuid",
58 | "static": false
59 | },
60 | {
61 | "name": "text",
62 | "typeDefinition": "text",
63 | "static": false
64 | },
65 | {
66 | "name": "key",
67 | "typeDefinition": "text",
68 | "static": false
69 | },
70 | {
71 | "name": "completed",
72 | "typeDefinition": "boolean"
73 | }
74 | ],
75 | "primaryKey": {
76 | "partitionKey": [
77 | "id"
78 | ]
79 | }
80 | })
81 |
82 | response = await astraRestClient.post('/api/rest/v2/schemas/keyspaces/todos/tables/' + name + '/indexes',
83 | {
84 | "column": "key",
85 | "name": "key_idx",
86 | "ifNotExists": true
87 | }
88 | );
89 | }
90 |
91 | const getRestClient = async () => {
92 | if (astraRestClient === null) {
93 | const astraRestClient = await getAstraRestClient();
94 | await wait(1000);
95 | return astraRestClient;
96 | };
97 | return astraRestClient;
98 | }
99 |
100 | module.exports = { getRestClient, requestWithRetry, wait, astraRestClient };
101 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | When contributing to this repository, please first discuss the change you wish to make via issue,
4 | email, or any other method with the owners of this repository before making a change.
5 |
6 | Please note we have a [Code of Conduct](CODE_OF_CONDUCT.md), please follow it in all your interactions with the project.
7 |
8 | ## Found an Issue?
9 | If you find a bug in the source code or a mistake in the documentation, you can help us by
10 | [submitting an issue](#submit-issue) to the GitHub Repository. Even better, you can
11 | [submit a Pull Request](#submit-pr) with a fix.
12 |
13 | ## Want a Feature?
14 | You can *request* a new feature by [submitting an issue](#submit-issue) to the GitHub
15 | Repository. If you would like to *implement* a new feature, please submit an issue with
16 | a proposal for your work first, to be sure that we can use it.
17 |
18 | * **Small Features** can be crafted and directly [submitted as a Pull Request](#submit-pr).
19 |
20 | ## Contribution Guidelines
21 |
22 | ### Submitting an Issue
23 | Before you submit an issue, search the archive, maybe your question was already answered.
24 |
25 | If your issue appears to be a bug, and hasn't been reported, open a new issue.
26 | Help us to maximize the effort we can spend fixing issues and adding new
27 | features, by not reporting duplicate issues. Providing the following information will increase the
28 | chances of your issue being dealt with quickly:
29 |
30 | * **Overview of the Issue** - if an error is being thrown a non-minified stack trace helps
31 | * **Motivation for or Use Case** - explain what are you trying to do and why the current behavior is a bug for you
32 | * **Reproduce the Error** - provide a live example or a unambiguous set of steps
33 | * **Suggest a Fix** - if you can't fix the bug yourself, perhaps you can point to what might be
34 | causing the problem (line of code or commit)
35 |
36 | ### Submitting a Pull Request (PR)
37 | Before you submit your Pull Request (PR) consider the following guidelines:
38 |
39 | * Search the repository (https://github.com/bechbd/[repository-name]/pulls) for an open or closed PR that relates to your submission. You don't want to duplicate effort.
40 |
41 | * Create a fork of the repo
42 | * Navigate to the repo you want to fork
43 | * In the top right corner of the page click **Fork**:
44 | 
45 |
46 | * Make your changes in the forked repo
47 | * Commit your changes using a descriptive commit message
48 | * In GitHub, create a pull request: https://help.github.com/en/articles/creating-a-pull-request-from-a-fork
49 | * If we suggest changes then:
50 | * Make the required updates.
51 | * Rebase your fork and force push to your GitHub repository (this will update your Pull Request):
52 |
53 | ```shell
54 | git rebase master -i
55 | git push -f
56 | ```
57 |
58 | That's it! Thank you for your contribution!
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as
6 | contributors and maintainers pledge to making participation in our project and
7 | our community a harassment-free experience for everyone, regardless of age, body
8 | size, disability, ethnicity, sex characteristics, gender identity and expression,
9 | level of experience, education, socio-economic status, nationality, personal
10 | appearance, race, religion, or sexual identity and orientation.
11 |
12 | ## Our Standards
13 |
14 | Examples of behavior that contributes to creating a positive environment
15 | include:
16 |
17 | * Using welcoming and inclusive language
18 | * Being respectful of differing viewpoints and experiences
19 | * Gracefully accepting constructive criticism
20 | * Focusing on what is best for the community
21 | * Showing empathy towards other community members
22 |
23 | Examples of unacceptable behavior by participants include:
24 |
25 | * The use of sexualized language or imagery and unwelcome sexual attention or
26 | advances
27 | * Trolling, insulting/derogatory comments, and personal or political attacks
28 | * Public or private harassment
29 | * Publishing others' private information, such as a physical or electronic
30 | address, without explicit permission
31 | * Other conduct which could reasonably be considered inappropriate in a
32 | professional setting
33 |
34 | ## Our Responsibilities
35 |
36 | Project maintainers are responsible for clarifying the standards of acceptable
37 | behavior and are expected to take appropriate and fair corrective action in
38 | response to any instances of unacceptable behavior.
39 |
40 | Project maintainers have the right and responsibility to remove, edit, or
41 | reject comments, commits, code, wiki edits, issues, and other contributions
42 | that are not aligned to this Code of Conduct, or to ban temporarily or
43 | permanently any contributor for other behaviors that they deem inappropriate,
44 | threatening, offensive, or harmful.
45 |
46 | ## Scope
47 |
48 | This Code of Conduct applies both within project spaces and in public spaces
49 | when an individual is representing the project or its community. Examples of
50 | representing a project or community include using an official project e-mail
51 | address, posting via an official social media account, or acting as an appointed
52 | representative at an online or offline event. Representation of a project may be
53 | further defined and clarified by project maintainers.
54 |
55 | ## Enforcement
56 |
57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
58 | reported by contacting the project team at . All
59 | complaints will be reviewed and investigated and will result in a response that
60 | is deemed necessary and appropriate to the circumstances. The project team is
61 | obligated to maintain confidentiality with regard to the reporter of an incident.
62 | Further details of specific enforcement policies may be posted separately.
63 |
64 | Project maintainers who do not follow or enforce the Code of Conduct in good
65 | faith may face temporary or permanent repercussions as determined by other
66 | members of the project's leadership.
67 |
68 | ## Attribution
69 |
70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
72 |
73 | [homepage]: https://www.contributor-covenant.org
74 |
75 | For answers to common questions about this code of conduct, see
76 | https://www.contributor-covenant.org/faq
77 |
--------------------------------------------------------------------------------
/src/index.css:
--------------------------------------------------------------------------------
1 | html,
2 | body {
3 | margin: 0;
4 | padding: 0;
5 | }
6 |
7 | button {
8 | margin: 10;
9 | padding: 10;
10 | border: 0;
11 | background: none;
12 | font-size: 90%;
13 | vertical-align: baseline;
14 | font-family: inherit;
15 | font-weight: inherit;
16 | color: inherit;
17 | -webkit-appearance: none;
18 | appearance: none;
19 | -webkit-font-smoothing: antialiased;
20 | -moz-osx-font-smoothing: grayscale;
21 | }
22 |
23 | body {
24 | font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif;
25 | line-height: 1.4em;
26 | background: #f5f5f5;
27 | color: #111111;
28 | min-width: 230px;
29 | margin: 0 auto;
30 | -webkit-font-smoothing: antialiased;
31 | -moz-osx-font-smoothing: grayscale;
32 | font-weight: 300;
33 | }
34 |
35 | :focus {
36 | outline: 0;
37 | }
38 |
39 | .hidden {
40 | display: none;
41 | }
42 |
43 | .todoapp {
44 | background: #fff;
45 | margin: 140px 0 40px 0;
46 | padding: 20px;
47 | position: relative;
48 | /*width: 80%;*/
49 | box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2),
50 | 0 25px 50px 0 rgba(0, 0, 0, 0.1);
51 | }
52 |
53 | .todoapp input::-webkit-input-placeholder {
54 | font-style: italic;
55 | font-weight: 300;
56 | color: rgba(0, 0, 0, 0.4);
57 | }
58 |
59 | .todoapp input::-moz-placeholder {
60 | font-style: italic;
61 | font-weight: 300;
62 | color: rgba(0, 0, 0, 0.4);
63 | }
64 |
65 | .todoapp input::input-placeholder {
66 | font-style: italic;
67 | font-weight: 300;
68 | color: rgba(0, 0, 0, 0.4);
69 | }
70 |
71 | .todoapp h1 {
72 | position: absolute;
73 | top: -100px;
74 | font-size: 50px;
75 | font-weight: 200;
76 | text-align: center;
77 | -webkit-text-rendering: optimizeLegibility;
78 | -moz-text-rendering: optimizeLegibility;
79 | text-rendering: optimizeLegibility;
80 | }
81 |
82 | .new-todo,
83 | .edit {
84 | position: relative;
85 | margin: 0;
86 | width: 100%;
87 | font-size: 20px;
88 | font-family: inherit;
89 | font-weight: inherit;
90 | line-height: 1.4em;
91 | color: inherit;
92 | padding: 6px;
93 | border: 1px solid #999;
94 | box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2);
95 | box-sizing: border-box;
96 | -webkit-font-smoothing: antialiased;
97 | -moz-osx-font-smoothing: grayscale;
98 | }
99 |
100 | .new-todo {
101 | padding: 16px 16px 16px 60px;
102 | border: none;
103 | background: rgba(0, 0, 0, 0.003);
104 | box-shadow: inset 0 -2px 1px rgba(0,0,0,0.03);
105 | }
106 |
107 | .main {
108 | position: relative;
109 | z-index: 2;
110 | border-top: 1px solid #e6e6e6;
111 | }
112 |
113 | .toggle-all {
114 | width: 1px;
115 | height: 1px;
116 | border: none; /* Mobile Safari */
117 | opacity: 0;
118 | position: absolute;
119 | right: 100%;
120 | bottom: 100%;
121 | }
122 |
123 | .toggle-all + label {
124 | width: 60px;
125 | height: 34px;
126 | font-size: 0;
127 | position: absolute;
128 | top: -52px;
129 | left: -13px;
130 | -webkit-transform: rotate(90deg);
131 | transform: rotate(90deg);
132 | }
133 |
134 | .toggle-all + label:before {
135 | content: '❯';
136 | font-size: 22px;
137 | color: #e6e6e6;
138 | padding: 10px 27px 10px 27px;
139 | }
140 |
141 | .css-3tmnuj {
142 | font-size: 18px !important;
143 | line-height: 1em;
144 |
145 | }
146 |
147 | .css-e393sm span {
148 | line-height: 15px;
149 | }
150 |
151 | .css-y965hj {
152 | font-size: 18px !important;
153 | padding-bottom: 5px;
154 | }
155 |
156 | .toggle-all:checked + label:before {
157 | color: #737373;
158 | }
159 |
160 | .todo-list {
161 | margin: 0;
162 | padding: 0;
163 | list-style: none;
164 | }
165 |
166 | .todo-list li {
167 | position: relative;
168 | font-size: 24px;
169 | border-bottom: 1px solid #ededed;
170 | }
171 |
172 | .todo-list li:last-child {
173 | border-bottom: none;
174 | }
175 |
176 | .todo-list li.editing {
177 | border-bottom: none;
178 | padding: 0;
179 | }
180 |
181 | .todo-list li.editing .edit {
182 | display: block;
183 | width: calc(100% - 43px);
184 | padding: 12px 16px;
185 | margin: 0 0 0 43px;
186 | }
187 |
188 | .todo-list li.editing .view {
189 | display: none;
190 | }
191 |
192 | .todo-list li .toggle {
193 | text-align: center;
194 | width: 40px;
195 | /* auto, since non-WebKit browsers doesn't support input styling */
196 | height: auto;
197 | position: absolute;
198 | top: 0;
199 | bottom: 0;
200 | margin: auto 0;
201 | border: none; /* Mobile Safari */
202 | -webkit-appearance: none;
203 | appearance: none;
204 | }
205 |
206 | .todo-list li .toggle {
207 | opacity: 0;
208 | }
209 |
210 | h1 {
211 | /*color: green*/
212 | }
213 |
214 | li.completed label {
215 | /*color: lightgreen;*/
216 | text-decoration: line-through;
217 | }
218 |
219 | li label{
220 | /*color: green*/
221 | }
222 |
223 | .todo-list li .toggle + label {
224 | /*
225 | Firefox requires `#` to be escaped - https://bugzilla.mozilla.org/show_bug.cgi?id=922433
226 | IE and Edge requires *everything* to be escaped to render, so we do that instead of just the `#` - https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/7157459/
227 | */
228 | background-image: url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23ededed%22%20stroke-width%3D%223%22/%3E%3C/svg%3E');
229 | background-repeat: no-repeat;
230 | background-position: center left;
231 | }
232 |
233 | .todo-list li .toggle:checked + label {
234 | background-image: url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23bddad5%22%20stroke-width%3D%223%22/%3E%3Cpath%20fill%3D%22%235dc2af%22%20d%3D%22M72%2025L42%2071%2027%2056l-4%204%2020%2020%2034-52z%22/%3E%3C/svg%3E');
235 | }
236 |
237 | .todo-list li label {
238 | word-break: break-all;
239 | padding: 15px 15px 15px 60px;
240 | display: block;
241 | line-height: 1.2;
242 | transition: color 0.4s;
243 | font-weight: 400;
244 | }
245 |
246 |
247 | .todo-list li .destroy {
248 | display: none;
249 | position: absolute;
250 | top: 0;
251 | right: 10px;
252 | bottom: 0;
253 | width: 40px;
254 | height: 40px;
255 | margin: auto 0;
256 | font-size: 30px;
257 | color: #cc9a9a;
258 | margin-bottom: 11px;
259 | transition: color 0.2s ease-out;
260 | }
261 |
262 | .todo-list li .destroy:hover {
263 | color: #af5b5e;
264 | }
265 |
266 | .todo-list li .destroy:after {
267 | content: '×';
268 | }
269 |
270 | .todo-list li:hover .destroy {
271 | display: block;
272 | }
273 |
274 | .todo-list li .edit {
275 | display: none;
276 | }
277 |
278 | .todo-list li.editing:last-child {
279 | margin-bottom: -1px;
280 | }
281 |
282 | .footer {
283 | padding: 10px 15px;
284 | height: 20px;
285 | text-align: center;
286 | font-size: 12px;
287 | border-top: 1px solid #e6e6e6;
288 | }
289 |
290 | .footer:before {
291 | content: '';
292 | position: absolute;
293 | right: 0;
294 | bottom: 0;
295 | left: 0;
296 | height: 50px;
297 | overflow: hidden;
298 | box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2),
299 | 0 8px 0 -3px #f6f6f6,
300 | 0 9px 1px -3px rgba(0, 0, 0, 0.2),
301 | 0 16px 0 -6px #f6f6f6,
302 | 0 17px 2px -6px rgba(0, 0, 0, 0.2);
303 | }
304 |
305 | .todo-count {
306 | float: left;
307 | text-align: left;
308 | }
309 |
310 | .todo-count strong {
311 | font-weight: 300;
312 | }
313 |
314 | .filters {
315 | margin: 0;
316 | padding: 0;
317 | list-style: none;
318 | position: absolute;
319 | right: 0;
320 | left: 0;
321 | }
322 |
323 | .filters li {
324 | display: inline;
325 | }
326 |
327 | .filters li a {
328 | color: inherit;
329 | margin: 3px;
330 | padding: 3px 7px;
331 | text-decoration: none;
332 | border: 1px solid transparent;
333 | border-radius: 3px;
334 | }
335 |
336 | .filters li a:hover {
337 | border-color: rgba(175, 47, 47, 0.1);
338 | }
339 |
340 | .filters li a.selected {
341 | border-color: rgba(175, 47, 47, 0.2);
342 | }
343 |
344 | .clear-completed,
345 | html .clear-completed:active {
346 | float: right;
347 | position: relative;
348 | line-height: 20px;
349 | text-decoration: none;
350 | cursor: pointer;
351 | }
352 |
353 | .clear-completed:hover {
354 | text-decoration: underline;
355 | }
356 |
357 | .info {
358 | margin: 65px auto 0;
359 | color: #4d4d4d;
360 | font-size: 11px;
361 | text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
362 | text-align: center;
363 | }
364 |
365 | .info p {
366 | line-height: 1;
367 | }
368 |
369 | .info a {
370 | color: inherit;
371 | text-decoration: none;
372 | font-weight: 400;
373 | }
374 |
375 | .info a:hover {
376 | text-decoration: underline;
377 | }
378 |
379 | /*
380 | Hack to remove background from Mobile Safari.
381 | Can't use it globally since it destroys checkboxes in Firefox
382 | */
383 | @media screen and (-webkit-min-device-pixel-ratio:0) {
384 | .toggle-all,
385 | .todo-list li .toggle {
386 | background: none;
387 | }
388 |
389 | .todo-list li .toggle {
390 | height: 40px;
391 | }
392 | }
393 |
394 | @media (max-width: 430px) {
395 | .footer {
396 | height: 50px;
397 | }
398 |
399 | .filters {
400 | bottom: 10px;
401 | }
402 | }
403 |
404 | .todo-console {
405 | background-color: #242424;
406 | /*background: rgba(97, 175, 254, 0.3);*/
407 | font-size: 20px;
408 | margin-top: 20px;
409 | padding-top: 10px;
410 | box-sizing: border-box;
411 | height: 450px;
412 | overflow-y: scroll;
413 | }
414 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | # TODO + Astra + Cassandra 📒
3 | *10 minutes, Beginner, [Start Building](https://github.com/DataStax-Examples/todo-astra-jamstack-netlify#prerequisites)*
4 |
5 | This is an example React To-Do application using a [DataStax Astra](https://astra.dev/9-9) free tier database.
6 |
7 |
8 | 
9 |
10 | ## 🎯 Objectives
11 | * Create a "from scratch" **React** app using NPX
12 | * Learn about **React** components and how they are used to dynamically update the DOM with new information
13 | * Learn how **state** and **props** changes are used
14 | * Learn how to use Swagger to interact with the database using a **REST** API
15 | * Leverage Netlify and DataStax Astra DB
16 |
17 | ## ℹ️ Frequently asked questions ℹ️
18 |
19 | - *Can I run the workshop on my computer?*
20 |
21 | > There is nothing preventing you from running the workshop on your own machine.
22 | > If you do so, you will need
23 | > * git installed on your local system
24 | > * [node 15 and npm 7 or later](https://www.whitesourcesoftware.com/free-developer-tools/blog/update-node-js/)
25 | >
26 | > You will have to adapt commands and paths based on your environment and install the dependencies by yourself. **We won't provide support** to keep on track with schedule. However, we will do our best to give you the info you need to be successful.
27 |
28 | - *What other prerequisites are there?*
29 | > * You will need a github account
30 | > * You will also need an Astra DB account, but we'll work through that in the exercises
31 | > * Use **Chrome** or **Firefox** for the best experience. Other browsers are great, but don't work well with the GitPod integration we use a bit later.
32 |
33 | - *Do I need to pay for anything for this workshop?*
34 | > * **No.** All tools and services we provide here are FREE.
35 |
36 | - *Will I get a certificate if I attend this workshop?*
37 |
38 | > Attending the session is not enough. You need to complete the homework detailed below and you will get a nice badge.
39 |
40 | ## Materials for the Session
41 |
42 | It doesn't matter if you join our workshop live or you prefer to do at your own pace, we have you covered. In this repository, you'll find everything you need for this workshop:
43 |
44 | - [Slide deck](./slides.pdf)
45 | - [Discord chat](https://bit.ly/cassandra-workshop)
46 | - [Questions and Answers](https://community.datastax.com/)
47 |
48 | ## Homework
49 |
50 |
51 |
52 | Don't forget to complete your upgrade and get your verified skill badge! Finish and submit your homework!
53 |
54 | 1. Complete the practice steps from this repository as described below.
55 | 2. Create a **React** app from scratch using NPX. Follow [these](https://github.com/datastaxdevs/react-basics) instructions. **Take a screenshot of your final working app**.
56 | 3. Launch the TODO starter app, connect it to the database, and display your changes from the database. **Take a screenshot of your TODO app with your unique entries**.
57 | 4. Submit your homework [here](https://github.com/datastaxdevs/appdev-week1-todolist/issues/new?assignees=HadesArchitect%2C+SonicDMG%2C+RyanWelford&labels=homework%2C+wait+for+review&template=homework-assignment.md&title=%5BHW%5D+%3CNAME%3E). Note:
58 | _never share your Astra DB tokens!_
59 |
60 | That's it, you are done! Expect an email next week!
61 |
62 | # Let's start
63 |
64 | ## Table of contents
65 |
66 | 1. [Login or Register to AstraDB and create database](#1-login-or-register-to-astradb-and-create-database)
67 | 2. [Create a security token](#2-create-a-security-token)
68 | 3. [Create a table with REST API using Swagger](#3-create-a-table-with-rest-api-using-swagger)
69 | 4. [Insert data in the Table with the REST API using Swagger](#4-insert-data-in-the-table-with-the-rest-api-using-swagger)
70 | 5. [Retrieving values](#5-retrieving-values)
71 | 6. [Launch GitPod IDE](#6-launch-gitpod-ide)
72 | 7. [Launch the TODO app](#7-launch-the-todo-app)
73 |
74 | ## An introduction to web development
75 | ### CodePen starter examples
76 | - [HTML](https://codepen.io/DatastaxDevs/pen/WNjrXXp)
77 | - [CSS](https://codepen.io/DatastaxDevs/pen/QWvyOOv)
78 | - [Javascript](https://codepen.io/DatastaxDevs/pen/mdmVRwy)
79 |
80 | ## 1. Login or Register to AstraDB and create database
81 | **`ASTRADB`** is the simplest way to run Cassandra with zero operations at all - just push the button and get your cluster. No credit card required, $25.00 USD credit every month, roughly 5M writes, 30M reads, 40GB storage monthly - sufficient to run small production workloads.
82 |
83 | ### ✅ Step 1a: Click the button to login or register with Datastax. You can use your `Github`, `Google` accounts or register with an `email`.
84 |
85 | _Make sure to chose a password with minimum 8 characters, containing upper and lowercase letters, at least one number and special character_
86 |
87 |
88 | - Show me!
89 |
90 |
91 |
92 | **Use the following values when creating the database**
93 | |Field| Value|
94 | |---|---|
95 | |**database name**| `todos_workshop_db` |
96 | |**keypace**| `todos` |
97 | |**Cloud Provider**| *Use the one you like, click a cloud provider logo, pick an Area in the list and finally pick a region.* |
98 |
99 | _You can technically use whatever you want and update the code to reflect the keyspace. This is really to get you on a happy path for the first run._
100 |
101 | You will see your new database `pending` in the Dashboard.
102 |
103 | 
104 |
105 | The status will change to `Active` when the database is ready, this will only take 2-3 minutes. You will also receive an email when it is ready.
106 |
107 | [🏠 Back to Table of Contents](#table-of-contents)
108 |
109 | ## 2. Create a security token
110 |
111 | ✅ **Step 2a:** [Create a token for your app](https://docs.datastax.com/en/astra/docs/manage-application-tokens.html) to use in the settings screen. Use "Database Administrator" permission.
112 |
113 | ✅ **Step 2b:** Copy the token value (eg `AstraCS:KDfdKeNREyWQvDpDrBqwBsUB:ec80667c....`) in your clipboard and save the CSV, this value would not be provided afterward.
114 |
115 | **👁️ Expected output**
116 | - Show me!
117 |
118 |
119 |
120 | [🏠 Back to Table of Contents](#table-of-contents)
121 |
122 | ## 3. Create a table with REST API using Swagger
123 |
124 | ✅ **Step 3a:** Open **Swagger** by
125 | 1. Click on your active database
126 | 2. Click `Connect` TAB
127 | 3. Click `REST API`
128 | 4. Clik link to your swagger endpoint.
129 |
130 | *As shown on the picture below.*
131 | 
132 |
133 | ✅ **Step 3b:** Navigate to **create a table** section
134 |
135 | 1. Once **Swagger** is launched, scroll down and navigate to the **schemas** section
136 |
137 | 
138 |
139 | 2. Then, within the **schemas** section navigate to **Create a table** and click on it to open the section.
140 | - Take particular note of the REST URI **/api/rest/v2/schemas/keyspaces/{keyspaceName}/tables**.
141 | - Also take note this is using a **POST** command.
142 |
143 | 
144 |
145 | 3. Click the "Try it out" button
146 |
147 | 
148 |
149 | ✅ **Step 3c:** Create table **restfromreadme_by_id**
150 |
151 | 1. Enter your **Astra token _(X-Cassandra-Token)_**
152 | 2. Enter the **keyspaceName** `todos`
153 |
154 | 
155 |
156 | 3. Finally, copy the create table statement using the code below into the **body** field
157 | ```json
158 | {
159 | "name": "restfromreadme_by_id",
160 | "ifNotExists": true,
161 | "columnDefinitions": [
162 | {
163 | "name": "id",
164 | "typeDefinition": "uuid",
165 | "static": false
166 | },
167 | {
168 | "name": "text",
169 | "typeDefinition": "text",
170 | "static": false
171 | },
172 | {
173 | "name": "key",
174 | "typeDefinition": "text",
175 | "static": false
176 | },
177 | {
178 | "name": "completed",
179 | "typeDefinition": "boolean"
180 | }
181 | ],
182 | "primaryKey": {
183 | "partitionKey": [
184 | "id"
185 | ]
186 | }
187 | }
188 | ```
189 |
190 | 4. And click **execute** to apply the command and create the table
191 |
192 | 
193 |
194 | You should see a **201** response telling you it correctly created the "restfromreadme_by_id" table.
195 |
196 | Again, take a note of the Request URL that was used to create the table. This comes into play later when we take a look at the code in `astraRestClient.js` used to create our TODO application table.
197 |
198 | 
199 |
200 |
201 | [🏠 Back to Table of Contents](#table-of-contents)
202 |
203 | ## 4. Insert data in the Table with the REST API using Swagger
204 | Now that we have a table to use, let's insert a row of data into the table, again using REST to do so.
205 |
206 | ✅ **Step 4a:** Navigate to **Add row** section
207 |
208 | 1. Scroll down and navigate to the **data** section
209 | 2. Then find **Add row** and click it to open the section
210 | - Also take note this is using a **POST** command.
211 | 3. Click **Try it out** just like we did previously
212 |
213 | 
214 |
215 | ✅ **Step 4b:** FIll in values and add a row
216 |
217 | 1. Add your Astra token
218 | 2. Add the keyspaceName `todos`
219 | 3. Add the tableName `restfromreadme_by_id`. Note, this is the table we created in the earlier step
220 |
221 | 
222 |
223 | 4. Copy the following JSON into the **body**
224 |
225 | ```json
226 | {"id":"57dbd260-d905-11eb-b985-c522859819b9","completed":false,"text":"TODO FROM README","key":"none"}
227 | ```
228 |
229 | 5. Click **Execute**. You should see code **201** in the response telling you it was a success and displaying the id of the row you just created.
230 |
231 |
232 | [🏠 Back to Table of Contents](#table-of-contents)
233 |
234 | ## 5. Retrieving values
235 | Finally, now that we created a table and inserted a row of data let's **GET** the data back out.
236 |
237 | ✅ **Step 5a:** Navigate to **Retrieve all rows** section
238 |
239 | 1. Scroll up within the **data** section
240 | 2. Then find **Retrieve all rows** and click it to open the section
241 | - Take note this is using a **GET** command.
242 | 3. Click **Try it out** just like we did previously
243 |
244 | 
245 |
246 | ✅ **Step 5b:** Execute the command to display the data
247 |
248 | 1. Enter your **Astra token _(X-Cassandra-Token)_**
249 | 2. Enter the **keyspaceName** `todos`
250 | 3. Enter the **tableName** `restfromreadme_by_id`
251 |
252 | 
253 |
254 | 4. Click **Execute**
255 | 5. View the end result data that should be exactly what we created in the previous step
256 |
257 | 
258 |
259 | [🏠 Back to Table of Contents](#table-of-contents)
260 |
261 | ## 6. Launch GitPod IDE
262 | - Click the button to launch the GitPod IDE.
263 |
264 | [](https://gitpod.io/#https://github.com/datastaxdevs/appdev-week1-todolist/)
265 |
266 | # Need a refresher on React Basics?
267 | Take me to the React stuff
268 | We've created a separate repo going over the Basics of React. To get there, click the link below.
269 |
270 | [GOTO React-Basics](https://github.com/datastaxdevs/react-basics)
271 |
272 | When you're done, just click on the "Back to Main" breadcrumb to come back here.
273 |
274 |
275 | ## 7. Launch the TODO app
276 |
277 | ✅ **Step 7a:** Retrieve application token to securely connect to the database
278 |
279 | Use the token you previously generated. If you no longer have the token and did not download a .csv, you can generate a new token using [the instructions above](#2-create-a-security-token)
280 |
281 | ✅ **Step 7b:** Configure Environment Variables and Install Dependencies
282 |
283 | 1. Create `.env` file
284 |
285 | In the repository directory run the following command to set up your Astra environment. Note that this does require Node 15 and NPM 7 to work. You can install a node version manager like `nvm` or `n` to use multiple versions on your system.
286 | ```bash
287 | npm exec astra-setup todos_workshop_db todos
288 | ```
289 |
290 | 2. 👩💻 Install all the packages
291 |
292 | ```bash
293 | npm install -g netlify-cli
294 | ```
295 |
296 | ✅ **Step 7c:** Launch your app
297 | * Run the application
298 | ```
299 | netlify dev
300 | ```
301 | * The application should automatically launch in the GitPod preview pane
302 |
303 |
304 | ### Things to Note:
305 | - The contents of this repo are based on [Jake's port](https://github.com/tjake/todo-astra-react-serverless/) of the [TodoMVC code](https://github.com/tastejs/todomvc/tree/master/examples/react) originally written by [Pete Hunt](https://github.com/petehunt).
306 | - The example is modified from https://github.com/huksley/todo-react-ssr-serverless.
307 |
308 |
--------------------------------------------------------------------------------