Skip to content

fix(repository): fix repo view when repos return 404 #726

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

dhamanutd
Copy link
Contributor

@dhamanutd dhamanutd commented Feb 14, 2018

instead of blank view, now will show not found message when error 404

BREAKING CHANGE: fix repository view when the repos 404 not found

fix #690

Question Response
Version? v1.4.1
Devices tested? OnePlus One
Bug fix? yes
New feature? yes/no
Includes tests? no
All Tests pass? yes
Related ticket? #690

Screenshots

Before After
before after

Description

  • Change action reducer getRepository to return Promise reject when response status code is not 200 OK
  • Make notFoundMsg props in the repository screen and component to take string from github api when return 404.
  • Change repository reducer in GET_REPOSITORY.ERROR to return initialState instead of recent state.
    • In purpose to make repository screen not showing any info from latest state, if there are error 404.
  • Create logic to show not found messages, hide owner section, and disabled view code button if error 404.

@coveralls
Copy link

coveralls commented Feb 14, 2018

Coverage Status

Coverage increased (+0.08%) to 44.863% when pulling 7f23a51 on dhamanutd:repo-screen-problem-when-repo-404 into 3b92054 on gitpoint:master.

Copy link
Member

@chinesedfan chinesedfan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dhamanutd Great new feature! Waiting for your feedbacks about my comments.

@@ -49,6 +49,7 @@ const mapStateToProps = state => ({
isPendingTopics: state.repository.isPendingTopics,
isPendingSubscribe: state.repository.isPendingSubscribe,
topics: state.repository.topics,
notFoundMsg: state.repository.error.message,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally, I prefer errorMessage or error directly. Then we can handle other types of errors and other information about errors in the future.

underlayColor={colors.greyLight}
disabled={(notFoundMsg && true) || false}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

disabled={!!notFoundMsg} will be simpler.

@@ -12,6 +12,7 @@ type Props = {
loading: boolean,
subscribed: boolean,
locale: string,
notFoundMsg: string,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think notFoundMsg is an inner state, which will not be customized from outside frequently. So we can add a new prop called error, hasError, or simply determinate it by repository.name.

@@ -133,7 +135,7 @@ export const RepositoryProfile = ({
)}

<Text style={[styles.languageInfoTitle]}>
{repository.language || ' '}
{notFoundMsg || repository.language || ' '}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try to add a new field in all files of locale/languages, say repository.unknowLanguage or something else you think better. Then rewrite as,

repository.language || translate('repository.unknowLanguage', locale)

Copy link
Contributor Author

@dhamanutd dhamanutd Feb 14, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@chinesedfan can i use google translate for another translation?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dhamanutd No, please just leave them in English. Other contributors will pick them up and translate.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice feature. Just an observation, the key has a typo, should be unknownLanguage.

(notFoundMsg && 'stop') ||
(repository.fork && 'repo-forked') ||
'repo'
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As we forbid nested ternary expressions, please extract as a function to make it more readable.

type="octicon"
size={45}
color={colors.greyLight}
/>

<Text style={styles.title}>{repository.name || ' '}</Text>
<Text style={styles.title}>{notFoundMsg || repository.name || ' '}</Text>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is that mean, you want make "Unkown" or "Not Found" as default, right?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My point is that the current "Not Found" is a message returned by Github API. Setting it as the value of Text directly will make the usage of this Text unclear. We'd better,

  • declare a corresponding string constant to represent special repository name, as I said before
  • or, create another certain UI component (maybe like a Toast) to show it

Copy link
Contributor Author

@dhamanutd dhamanutd Feb 15, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@chinesedfan if want to use Toast, i will install library react-native-simple-toast. What do you think? does it needed? Because toast from react native didn't support iOS

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, I don't mind to introduce a new library as long as it is useful. And we can also wait for some feedbacks from other reviewers, like @machour.

src/api/index.js Outdated
return response.json();
return response.ok
? response.json()
: response.json().then(err => Promise.reject(err));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In fact, response.json().then(err => Promise.reject(err)) is the same with response.json(). You handle the error in then and throw out identically. Please correct me if I misunderstood your thinking.

Copy link
Contributor Author

@dhamanutd dhamanutd Feb 14, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@chinesedfan
this because when the response status is 4xx it always handled by .then(), that's why i give return Promise.reject to make it handled by .catch(). But if you think there better way to distinct beetween 200 OK and 4xx Error, let me know.

Another suggestion from me is to implement Axios and Redux-Saga to the app for better handling failures.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dhamanutd I see. Then you can modify getRepository to call v3.call, and check response.status. Please refer to checkReadMe.

instead of blank view, now will show not found message when error 404

BREAKING CHANGE: fix repository view when the repos 404 not found

fix gitpoint#690
simpler ternary and change nested ternary to a function instead, delete props that not needed
anymore.
repository.main.unknowLanguage and repository.main.notFoundRepo
@dhamanutd dhamanutd force-pushed the repo-screen-problem-when-repo-404 branch from a7520f5 to 440d091 Compare February 14, 2018 12:28
give logical promise in the getRepository action reducer and add new state.repository.hasRepoExist
to make Toast also supported in iOS.
@dhamanutd
Copy link
Contributor Author

@chinesedfan i did some of you requested to changes. you can review it now.

Copy link
Member

@chinesedfan chinesedfan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dhamanutd Thanks for your fast update! We are almost there.

json = response.json().then(err => Promise.reject(err));
}

return json;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about writing in one line, return response.status === 200 ? response.json() : Promise.reject()?

@@ -39,6 +40,7 @@ const mapStateToProps = state => ({
starred: state.repository.starred,
forked: state.repository.forked,
subscribed: state.repository.subscribed,
hasRepoExist: state.repository.hasRepoExist,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shall we keep hasRepoExist and error together? Or either is enough?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually i want to remove error. But as you said before, you said maybe it will be used in future.

So, will me to delete that?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer to keep error, because error is needed for Toast, while hasRepoExist can be replaced by !error. What do you think about?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@chinesedfan i think hasRepoExist is only to set state if repo exist or not, but error is to get value whatever it is not only about repo exist or not. I think both are used.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, there are tricky differences between them. It requires us to handle these 2 fields more carefully.

@@ -177,6 +177,8 @@ export const en = {
},
repository: {
main: {
notFoundRepo: 'Repository is not found',
unknowLanguage: 'Unknown',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unknownLanguage as @arthurdenner suggested? Sorry I am not a native English speaker.

edit typo in translation simpler conditional to ternary, also edit fetchRepoInfo() promise to
.finally() instead of .then()
error: action.payload,
isPendingRepository: false,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just noticed that this line was removed. Do you want to keep pending state when an error occurs?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@chinesedfan it's because we take ...initialState that already had isPendingRepository state as false.

@@ -62,19 +63,21 @@ export const repositoryReducer = (state = initialState, action = {}) => {
return {
...state,
issues: [],
error: '',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you persist to keep 2 fields, I suggest to clear hasRepoExist when pending and error. If repo1 set it to be true, then repo2 will get wrong value during pending or error.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@chinesedfan in current changes, i've tried to test in real world. I don't face any problem when openning from one repo to another.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, as you reset with initialState, the error state is cleared. And the pending state is too fast to be noticed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Understand, okay i will set hasRepoExist when pending too

.then(response => {
return response.status === 200
? response.json()
: response.json().then(err => Promise.reject(err));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

response.json() will never throw an error, no matter response.status === 200 or not, right? So I think Promise.reject() is enough. We don't need to call response.json() again.

Copy link
Contributor Author

@dhamanutd dhamanutd Feb 18, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@chinesedfan if we just only using Promise.reject(), we will not pass any value from that. It will just call .catch() but didn't pass any data you get from API response. In this case we will not get the "Not Found" messages from github API.

That's why first i need to get json() data from API, then i pass that data in the Promise.reject(err).

I make both if true (equal 200) or false (not equal 200) will send same json formatted data.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dhamanutd Oh, hope I understand your idea this time. Do you mean response.json().then((json) => response.status === 200 ? json : Promise.reject(json))?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@chinesedfan yes, that's what i'm intended to

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good. Can you update it? Then I think there are no problems from my side. Thanks for your patient revisions!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

@housseindjirdeh housseindjirdeh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is great, thank you @dhamanutd :)

Just wanted to ask - how does the Toast show on Android? Can check it as well if we merge this in

@@ -740,6 +740,15 @@
"contributions": [
"code"
]
},
{
"login": "dhamanutd",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎉 🚀 🚀

@housseindjirdeh housseindjirdeh merged commit 86dd2f7 into gitpoint:master Mar 1, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Wrong info when i click on forked to
6 participants