Limit List View by Username:

Last part we passed more components in div blocks.

render the current user:

  • We just know what is passed in TweetsComponent

    • We can comment/delete console.log() in twittme-web/src/tweets/components.js this time: ```javascript export function TweetsComponent(props) { //console.log(props);

    //… } ```

  • change components in /twittme-web/public/index.html

    1. <body>
    2. <noscript>You need to enable JavaScript to run this app.</noscript>
    3. <!--
    4. <div id="tweetme-2" data-username="root" data-valid="true"></div>
    5. -->
    6. <div id="tweetme-2" data-username="root" data-can-tweet="false"></div>
    7. <!--
    8. This HTML file is a template.
    9. If you open it directly in the browser, you will see an empty page.
    10. You can add webfonts, meta tags, or analytics to this file.
    11. The build step will place the bundled scripts into the <body> tag.
    12. To begin the development, run `npm start` or `yarn start`.
    13. To create a production bundle, use `npm run build` or `yarn build`.
    14. -->
    15. </body>
  • and tweet_list_view /tweets/views.py to pickup username in ?username=[value] cases

    1. @api_view(['GET']) # http method the client === POST
    2. def tweet_list_view(request, *args, **kwargs):
    3. qs = Tweet.objects.all() # grab all objects in Tweet
    4. username = request.GET.get('username') # ?username=root
    5. if username != None:
    6. qs = qs.filter(user__username__iexact=username) # filter that username w/o case sensitive
    7. serializer = TweetSerializer(qs, many=True)
    8. return Response(serializer.data)

    runserver and npm start,
    access http://localhost/api/tweets/
    image.png
    access http://localhost/api/tweets/?username=root

  • actually there should be some differences for the first and the second list, but because sent username is still always root, and we have only one stuff user now, we should apply rendering method before to split tweets.

Rendering Limited Tweet List by Username:

From now on, we have to spilt tweet list by username if requested.

refer to a user:

  • we modify /twittme-web/public/index.html

    1. <body>
    2. <noscript>You need to enable JavaScript to run this app.</noscript>
    3. <!--
    4. <div id="tweetme-2" data-username="root" data-valid="true"></div>
    5. -->
    6. <div id="tweetme-2" data-username="cfe" data-can-tweet="false"></div>
    7. <!--
    8. ...
    9. -->
    10. </body>
  • in /twittme-web/src/tweets/lookup.js

    • modify endpoint if there is a username required
    • add a apiTweetDetail() to handle request of tweetid ```javascript

//export function apiTweetList(callback) { export function apiTweetList(username, callback) { let endpoint = “/tweets/“ if(username){ endpoint = /tweets/?username=${username} }

backendLookup(“GET”, endpoint, callback); //backendLookup(“GET”, “/tweets/“, callback); }

//new export function apiTweetDetail(tweetId, callback) { backendLookup(“GET”, /tweets/${tweetId}/, callback) }

  1. - also in /twittme-web/src/tweets/components.js
  2. - pass username to TweetsList
  3. - set default username as props.username in TweetsList
  4. ```javascript
  5. export function TweetsComponent(props) {
  6. //...
  7. return (
  8. //[...props] means username here
  9. <div className={props.className}>
  10. <div className="col-12 mb-3">
  11. <form onSubmit={handleSubmit}>
  12. <textarea
  13. ref={textAreaRef}
  14. required={true}
  15. className="form-control"
  16. name="tweet"
  17. ></textarea>
  18. <button type="submit" className="btn btn-primary my-3">
  19. Tweet
  20. </button>
  21. </form>
  22. </div>
  23. <TweetsList newTweets={newTweets} {...props} />
  24. </div>
  25. );
  26. /*
  27. return (
  28. <div className={props.className}>
  29. <div className="col-12 mb-3">
  30. <form onSubmit={handleSubmit}>
  31. <textarea
  32. ref={textAreaRef}
  33. required={true}
  34. className="form-control"
  35. name="tweet"
  36. ></textarea>
  37. <button type="submit" className="btn btn-primary my-3">
  38. Tweet
  39. </button>
  40. </form>
  41. </div>
  42. <TweetsList newTweets={newTweets} />
  43. </div>
  44. );
  45. */
  46. }
  47. export function TweetsList(props) {
  48. const [tweetsInit, setTweetsInit] = useState([]);
  49. const [tweets, setTweets] = useState([]);
  50. const [tweetsDidSet, setTweetsDidSet] = useState(false);
  51. useEffect(() => {
  52. const final = [...props.newTweets].concat(tweetsInit); //[...content] means a new list with the content
  53. if (final.length !== tweets.length) {
  54. setTweets(final);
  55. }
  56. }, [props.newTweets, tweets, tweetsInit]);
  57. useEffect(() => {
  58. if (tweetsDidSet === false) {
  59. const handleTweetListLookup = (response, status) => {
  60. if (status === 200) {
  61. setTweetsInit(response);
  62. setTweetsDidSet(true);
  63. } else {
  64. alert("There was an error");
  65. }
  66. };
  67. //apiTweetList(handleTweetListLookup);
  68. apiTweetList(props.username, handleTweetListLookup); //new
  69. }
  70. //}, [tweetsInit, tweetsDidSet, setTweetsDidSet]);
  71. }, [tweetsInit, tweetsDidSet, setTweetsDidSet, props.username]); //add a new dependency
  72. //...
  73. }

after that, refresh and test.
image.png
we only have 3 tweets sent by cfe, so http://localhost/api/tweets/?username=cfe shows
image.png
and if we use localhost:30 (reactjs page)
image.png
it also only shows 3 tweets.

because in /twittme-web/public/index.html


this block made passed username not null, and

the request of
http://localhost/api/tweets
becomes
http://localhost/api/tweets/?username=cfe

and only shows tweets sent by cfe.
(because of some reason, “root” become the source of all tweets sent, so I changed senders to cfe for test this time.)

apply “canTweet”:

If we request some user who don’t exist, it will return a null list instead of error.

  • only allow tweet when canTweet === True in /twittme-web/src/tweets/components.js

    1. export function TweetsComponent(props) {
    2. const textAreaRef = React.createRef();
    3. const [newTweets, setNewTweets] = useState([]);
    4. //passed canTweet is a string, not a boolean
    5. const canTweet = props.canTweet === "false" ? false : true
    6. const handleBackendUpdate = (response, status) => {
    7. let tempNewTweets = [...newTweets];
    8. if (status === 201) {
    9. tempNewTweets.unshift(response);
    10. setNewTweets(tempNewTweets);
    11. } else {
    12. console.log(response);
    13. alert("An error occured please try again");
    14. }
    15. };
    16. const handleSubmit = (event) => {
    17. event.preventDefault();
    18. const newVal = textAreaRef.current.value;
    19. console.log("new value", newVal);
    20. apiTweetCreate(newVal, handleBackendUpdate);
    21. textAreaRef.current = "";
    22. };
    23. return (
    24. <div className={props.className}>
    25. {canTweet === true &&
    26. <div className="col-12 mb-3">
    27. <form onSubmit={handleSubmit}>
    28. <textarea
    29. ref={textAreaRef}
    30. required={true}
    31. className="form-control"
    32. name="tweet"
    33. ></textarea>
    34. <button type="submit" className="btn btn-primary my-3">
    35. Tweet
    36. </button>
    37. </form>
    38. </div>
    39. }
    40. <TweetsList newTweets={newTweets} {...props} />
    41. </div>
    42. );
    43. /*
    44. return (
    45. <div className={props.className}>
    46. <div className="col-12 mb-3">
    47. <form onSubmit={handleSubmit}>
    48. <textarea
    49. ref={textAreaRef}
    50. required={true}
    51. className="form-control"
    52. name="tweet"
    53. ></textarea>
    54. <button type="submit" className="btn btn-primary my-3">
    55. Tweet
    56. </button>
    57. </form>
    58. </div>
    59. <TweetsList newTweets={newTweets} {...props} />
    60. </div>
    61. );
    62. */
    63. }

    refresh
    image.png
    so because we set the div block canTweet === “false”, the textarea for tweet disappeared.