Skip to content
This repository has been archived by the owner on Jun 17, 2021. It is now read-only.

Project configuration #120

Merged
merged 48 commits into from
Sep 9, 2018
Merged

Conversation

AWolf81
Copy link
Collaborator

@AWolf81 AWolf81 commented Aug 6, 2018

Related Issue: #28

Summary:

  • Adds an animated gear icon to ProjectPage
  • Opens a configuration modal for:
    • Project name
    • Project icon
  • Adds a temporary project.middleware - needs to be converted to Redux-Saga later after PR Queue/group actions that lock package.json #103

This branch is based on npm-to-yarn.

Todos:

  • Add Gear button to project pane to open modal (with hover effect scale, color & rotate)

  • Create ProjectModal

  • Add icon picker from CreateNewProject Wizard

  • Create basic settings modal

  • Check flow types

  • Remove not needed code (copied from TaskModal & not needed here)

  • Add gear rotation on hover

  • Used Redux-based modal (maybe needs to be improved later - at dynamic modal component based on state.modal)

  • Add Save

  • Cancel button - maybe later

  • Add business logic - Rename / change everything (similar to when the project is created):

    • Update guppy.name inside package.json
    • Use slug to get an alphanumeric+dash version of the new name, and set that to guppy.id inside package.json, as well as package.json's name field.
    • Rename the parent folder.
    • Refresh state to use the new project settings
    • Using uuid - no id renaming required
  • Display confirm for renaming at every project rename

  • Improve styling of project name text input & buttons

  • Check if package.json requires locking - wait for Queue and batch dependency actions #181

  • Create temporary middleware for renaming & modifying project folder & package.json - later change to Saga

  • Rework modal handling as mentioned in the issue either CurrentModal component or adding ProjectConfigurationModal after CreateProjectWizard to app.js - I need to check which is easier to maintain and more re-usable

  • Change Redux Action to single SAVE_PROJECT_SETTINGS action & remove Flow types for Redux --> check if we should create an issue for this.

  • Make ProjectIconSelection Component - for now code copied from CreateProjectWizard Will be refactored in a separate issue later

      <ProjectIconSelection
          selectedIcon={?string}
          showRandomSubset={boolean}
          onSelectIcon={function} />
    
  • Check initial loading? Maybe icons need a loading indication. Seems fast enough. Check directly after first app start - also looks OK.

  • Optimize renaming for imported projects & avoid brief flash of component with-out values (see second screenrecording)

  • Fix problem with paths.reducer - Path not found after clicking Nope in confirmation dialog during renaming an imported project. Also paths state object is always empty. It should work if we're getting guppy.path from package.json into paths state. Not sure what's wrong here. Update: Seems to be fixed after merging master & updating to Saga.

  • Check if SAVE_PROJECT_SETTINGS_START in project.middleware can be simplified. It's working but looks pretty complicated. Update: Simplified with re-write to a Saga.

  • Remove temporary project-save.middleware

  • Convert middleware to a Saga.

  • Add test to save-project-settings.saga

  • Test error handling e.g. rename or delete project externally or change permissions of directory.

Screen recording (gear & modal) - current version
screenrecording_project_config_11082018

Confirm for imported project
screenrecording_project_config_11082018_confirm

@superhawk610
Copy link
Collaborator

Since the gear wheel is a button, I would probably add cursor: pointer to indicate as much. The animation looks really nice 👍

Copy link
Owner

@joshwcomeau joshwcomeau left a comment

Choose a reason for hiding this comment

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

Excited to see this come together!

Unfortunately I do have a few things I'd like to see changed. The biggest is probably not changing the ID when the project name changes. We should still prompt the user to rename the folder, but I think changing the ID introduces a lot of complexity and potential issues, without having a clear benefit for the user.

Another thing I noticed is that this PR is still in a WIP state in some ways - lots of commented-out code, and debugging statements. I find it really helpful to review my own code when I open a PR, before adding reviewers, to help me catch this stuff before it gets to other reviewers. I initially added comments for stuff like this, but there's quite a few of them and I didn't want the more-important comments to get lost in the noise.

(FWIW I forget to do this, so I'm far from perfect myself haha. Just a good tip to try and remember)

Finally, it'd be great if you could try and create smaller PRs in the future. This can be pretty tough, but it makes it much easier to review. Often I'll create multiple PRs (choosing previous branches in the sequence as the target, instead of master), so that even not-fully-formed-features can have their own PR

Let me know if any feedback is unclear or shortsighted, happy to discuss!

360}deg) scale(${scale}, ${scale})`,
color: chroma
.interpolate(this.props.color, this.props.hoverColor, color)
.hex(),
Copy link
Owner

Choose a reason for hiding this comment

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

Interesting, I read through the chroma-js API docs and couldn't find an interpolate method o_O

I'm actually not sure we need to do this. My big hesitation is that color-changes will require a CPU repaint on every frame (whereas transform can happen entirely on the video card), so it might make the overall animation more stuttery on lower-end machines. I'm also a bit wary of adding another color library just for this (we already have NPM color, although Chroma looks like a better lib so I'd be up for switching... just have to update the existing color stuff).

Finally, I've been thinking about switching Guppy to use React Spring (https://github.com/drcmda/react-spring). It has a nicer API than React Motion, and comes with a few extra bells & whistles, like color interpolation built-in :o

So maybe for now we can omit the hover color change entirely, and consider re-adding it when we switch? I'd actually like to do the React Spring switch sooner rather than later, since it's a friendlier API. I might tackle that myself in the coming days.

Copy link
Owner

Choose a reason for hiding this comment

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

Ah, forgot about this!

I think for now we should just set the color without animation:

color: hovered ? this.props.hoverColor : this.props.color

I'm concerned about the performance of the rotation animation if we're also mutating the color, for reasons described above. And I think a hard switch probably looks fine :)

package.json Outdated
@@ -37,6 +37,7 @@
]
},
"dependencies": {
"chroma-js": "^1.3.7",
Copy link
Owner

Choose a reason for hiding this comment

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

Can we remove the caret, and put this in devDependencies instead of dependencies?

The reason is to avoid having stuff in node_modules with the shipped app, for anything compiled anyway by Webpack.

I added this to #210

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

OK, I'll move it and remove the caret.

I think once this PR is merge we could check if the chroma is really needed as I think the effect is almost not visible. It's blending the color of the gear icon.
But maybe we can use the blending elsewhere as I think this can be a nice effect if it is more visible.

@@ -13,7 +13,7 @@ import type {

//
//
// Action Types

Copy link
Owner

Choose a reason for hiding this comment

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

I think we still want this? Doesn't seem super important, but it should stay consistent with the Action creators comment below.

Mostly I like this as a way to separate out files that have different kinds of things, like this. It's helpful in reducers, for example, which can also have selectors and helpers.

If other people don't think they're necessary, we can remove it :) but then we should also remove // Action creators below.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Oh, this is probably removed accidentially. I'll add it back.
Not sure how this happened.

selectedProject: getSelectedProject(state),
isAppLoaded: getAppLoaded(state),
};
};
Copy link
Owner

Choose a reason for hiding this comment

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

Looks like this stuff didn't actually wind up changing, can you revert it to how it was? Removing the comment + using an implicit return.

(a helpful tip for debugging implicit returns: you can do stuff like this:

const mapStateToProps = state => ({
  selectedProject: console.log(getSelectedProject(state)) || getSelectedProject(state),
})

This way, you can log out the values of things without having to refactor it to have room for a statement at the top)

Copy link
Collaborator

Choose a reason for hiding this comment

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

So glad I'm not the only one that does this.

import React, { Component, Fragment } from 'react';
import { connect } from 'react-redux';
import styled from 'styled-components';
// import moment from 'moment';
Copy link
Owner

Choose a reason for hiding this comment

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

Nit: comment

// Should update state & close modal
});
});
});
Copy link
Owner

Choose a reason for hiding this comment

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

I think there's a bit more work to be done fleshing out these tests. I think it's important for new feature work that we have good test coverage :) we don't need to handle every edge-case, but we should go through the happy path and maybe the most common errors?

Copy link
Collaborator

Choose a reason for hiding this comment

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

I can try to tackle these tests tomorrow if you haven't gotten around to them by then.

remote.app.getAppPath(),
'./node_modules/yarn/bin',
formatCommandForPlatform(PACKAGE_MANAGER)
);
Copy link
Owner

Choose a reason for hiding this comment

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

This file is now named platform.service.js (I noticed a similar thing on another branch, not sure how this happened :/)

Please integrate any changes into that other file

src/types.js Outdated
@@ -25,7 +25,7 @@ export type DependencyStatus =
| 'updating'
| 'deleting';
export type DependencyLocation = 'dependencies' | 'devDependencies';
export type QueueAction = 'install' | 'uninstall';
export type QueueAction = 'install' | 'uninstall' | 'modify';
Copy link
Owner

Choose a reason for hiding this comment

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

I believe modify can be removed now that we aren't adding to the queue

src/types.js Outdated
@@ -92,6 +92,7 @@ export type ProjectInternal = {
color: string,
icon: string,
createdAt: number,
isImported: boolean,
Copy link
Owner

Choose a reason for hiding this comment

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

This also appears unused, outside of the middleware (which has been replaced with a saga)

src/utils.js Outdated
@@ -227,7 +227,7 @@ export const getTimeOfDay = () => {
}
};

export const hasPropChanged = (oldProps, newProps, key) => {
export const hasPropChanged: boolean = (oldProps, newProps, key) => {
Copy link
Owner

Choose a reason for hiding this comment

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

Nit: this annotation shouldn't be necessary, Flow is generally pretty good about inferring this. You can still add it, if you think it's helpful, but it isn't required.

expect(saga.next().value).toEqual(
takeEvery(START_NEXT_ACTION_IN_QUEUE, handleStartNextActionInQueue)
);
// expect(saga.next().value).toEqual( // Todo: Create queue.saga.test file
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@superhawk610 I think we need to create a queue.saga.test and move these lines there. Also the other queue related Saga tests should be moved there.
Is it OK to address this after this PR?

Copy link
Owner

Choose a reason for hiding this comment

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

Good catch!


expect(saga.next().value).toEqual(
put(
saveProjectSettingsFinish(undefined, 'project', 'path/to/new-project') // why is project undefined?
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@superhawk610 Do you have an idea why I have to pass undefined for the project here? Couldn't see what's wrong.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Ah, OK, I missed to pass the obejct to saga.next so there was no project passed. This is fixed. I'll push it in a minute.

@AWolf81
Copy link
Collaborator Author

AWolf81 commented Sep 5, 2018

Phew, I hope I've added everything.

At the moment, there is one failing test. Because of the refactoring in projects.reducer to a new case - I'll fix this later today.

Yeah, sorry, that this is pretty large. But I think it's that large because I had to start with the Windows-support branch so I could start to work on it. I think furture features should be smaller.

For the ID change:
I think we could address this after merging so this PR isn't getting even larger. I like to have the id like the name but I think a UUID inside of Guppy key should be no problem.

Copy link
Owner

@joshwcomeau joshwcomeau left a comment

Choose a reason for hiding this comment

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

Hey @AWolf81,

Wooo, it's looking great, thanks for making so many of the requested changes. The only request I found that wasn't addressed (either by changing the code, or in your comment above) was having SAVE_PROJECT_FINISH dismiss the modal instead of dispatching a hideModal(). This is not a big deal, though. I can tackle that afterwards, when I do some visual tweaks.

I do have a hesitation about approving this when there are still two things I think should be done:

  • Removing the logic to update the project ID when renaming
  • Adding tests for queue.saga.js

My rationale:

  • For the project-ID updating, my concern is that once we merge this in, other people will keep working on the code. If the code was contained to its own little section I'd be more OK with it, but it's in almost all of our main reducers (having to delete the entities and replace them with the new ID whenever the ID changes).

  • For the tests, I think we really wanna be pretty strict about making sure that all new code merged in has good test coverage, especially for critical business logic like managing the dependency queue.

I do hear what you're saying about this PR getting a bit long, so I have a proposal; what if you check out a new branch from this one, do those couple changes, and submit it for review (using this branch as the base instead of master). Then, we can approve that branch, merge it into this one, and then merge the whole thing into master.

Also, to clarify: I like the idea of using UUIDs for project IDs, but that's a bigger change than I think is necessary right now. For now, I think we can just leave the ID unchanged (so this should just be a matter of updating the ID-changing logic in save-project.saga, as well as removing the cases from the various reducers). I'd be happy to merge that in now, and create an issue to convert project IDs to uuids in the future.

Let me know how that sounds! I wanna try and be accommodating since you've worked so much on this, but I also think it's important to merge code we feel is 100% ready, especially as we get newer contributors who might build on whatever's in master.

render() {
const { hovered } = this.state;
return (
// Omitting most of the structure that isn't relevant
Copy link
Owner

Choose a reason for hiding this comment

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

What does this comment mean, what structure is omitted?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

mmhhh, not sure. I think that was a comment that was in your proposal. 😄
Maybe this is outdated. I'll remove it.

@@ -19,13 +21,18 @@ type State = 'new-project-wizard' | null;
const initialState = null;

export default (state: State = initialState, action: Action) => {
// console.log('action', action);
Copy link
Owner

Choose a reason for hiding this comment

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

stray comment

@@ -165,6 +185,7 @@ export const getInternalProjectById = (state: GlobalState, id: string) =>
getById(state)[id];

export const getProjectsArray = (state: GlobalState) => {
// console.log('get projects', state.projects);
Copy link
Owner

Choose a reason for hiding this comment

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

stray console.logs, here and on line 119

@@ -26,6 +26,10 @@ type State = {

const initialState = {};

// const addToQueue = (queueType: string, draftState: any) => {

// }
Copy link
Owner

Choose a reason for hiding this comment

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

stray comment

expect(saga.next().value).toEqual(
takeEvery(START_NEXT_ACTION_IN_QUEUE, handleStartNextActionInQueue)
);
// expect(saga.next().value).toEqual( // Todo: Create queue.saga.test file
Copy link
Owner

Choose a reason for hiding this comment

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

Good catch!

AWolf81 and others added 3 commits September 7, 2018 22:46
* added uuid & removed id change

* added root test

* isolate queue handling to queue saga

* removed commented code.

* move all queue testing to queue saga test
@AWolf81 AWolf81 mentioned this pull request Sep 8, 2018
Copy link
Owner

@joshwcomeau joshwcomeau left a comment

Choose a reason for hiding this comment

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

Yay excited to see this land! =D

As discussed, I'm gonna open a subsequent PR to tweak a couple things, but it shouldn't affect things too much, so I'm happy to merge this in now.

@joshwcomeau joshwcomeau merged commit 4593736 into joshwcomeau:master Sep 9, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants