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

Commit

Permalink
Merge pull request #123 from bisfun-hatfes/editable-ship-name
Browse files Browse the repository at this point in the history
Editable ship names
  • Loading branch information
arthyn authored Oct 26, 2021
2 parents ede30dd + 50784e6 commit bb279aa
Show file tree
Hide file tree
Showing 10 changed files with 92 additions and 14 deletions.
4 changes: 4 additions & 0 deletions src/background/services/pier-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export interface PierHandlers {
'get-piers': PierService["getPiers"]
'get-messages': PierService["getMessages"]
'get-pier-auth': PierService["getPierAuth"]
'update-pier': PierService["updatePier"]
'collect-existing-pier': PierService["collectExistingPier"]
'boot-pier': PierService["bootPier"]
'resume-pier': PierService["resumePier"]
Expand Down Expand Up @@ -70,6 +71,7 @@ export class PierService {
{ name: 'get-piers', handler: this.getPiers.bind(this) },
{ name: 'get-messages', handler: this.getMessages.bind(this) },
{ name: 'get-pier-auth', handler: this.getPierAuth.bind(this) },
{ name: 'update-pier', handler: this.updatePier.bind(this) },
{ name: 'collect-existing-pier', handler: this.collectExistingPier.bind(this) },
{ name: 'boot-pier', handler: this.bootPier.bind(this) },
{ name: 'resume-pier', handler: this.resumePier.bind(this) },
Expand Down Expand Up @@ -635,6 +637,8 @@ export type AddPier = Pick<Pier, 'name' | 'type' | 'shipName' | 'keyFile'> & {
directoryAsPierPath?: boolean;
}

export type UpdatePier = Pick<Pier, 'name' | 'type'>

export interface NewMoon {
name: string;
planet: string;
Expand Down
13 changes: 6 additions & 7 deletions src/renderer/details/components/NameField.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import React from 'react'
import { UseFormMethods } from 'react-hook-form/dist/types';
import { useQuery } from 'react-query';
import { AddPier } from '../../../background/services/pier-service';
import { AddPier, UpdatePier} from '../../../background/services/pier-service';
import { send } from '../../client/ipc';
import { pierKey } from '../../query-keys';

interface NameFieldProps {
form: UseFormMethods<AddPier>
form: UseFormMethods<AddPier | UpdatePier>
}

export const NameField: React.FC<NameFieldProps> = ({ form }) => {
Expand All @@ -32,16 +32,15 @@ export const NameField: React.FC<NameFieldProps> = ({ form }) => {
validate: nameValidator,
maxLength: 64
})}
className="input flex w-full mt-2"
placeholder="My Ship"
className="input flex w-full mt-2"
placeholder="My Ship"
aria-invalid={!!form.errors.name}
/>
<span className={`inline-block h-8.5 mt-2 text-xs text-red-600 ${form.errors?.name ? 'visible' : 'invisible'}`} role="alert">
<span className={`inline-block h-8.5 w-52 mt-2 text-xs text-red-600`} role="alert">
{ form.errors.name?.type === 'required' && 'Name is required'}
{ form.errors.name?.type === 'maxLength' && 'Name must be 64 characters or less'}
{ nameNotUnique && 'Name must be unique' }
{ /* need this for height? */ }
{ (!form.errors.name || nameContainsInvalidCharacters) && 'Name must only contain alphanumeric, dash, underscore, or space characters' }
{ nameContainsInvalidCharacters && 'Name must only contain alphanumeric, dash, underscore, or space characters' }
</span>
</>
)
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/details/pages/ExistingShipDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export const ExistingShipDetails = () => {
<label htmlFor="name">Name <span className="text-gray-300 dark:text-gray-700">(local only)</span></label>
<NameField form={form} />
</div>
<div className="mb-8">
<div className="mt-2 mb-8">
<label htmlFor="type">Ship Type</label>
<select name="type" ref={form.register({ required: true })} className="input ml-3 bg-white dark:bg-black">
<option value="planet">Planet</option>
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/details/pages/MoonDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export const MoonDetails: React.FC = () => {
<label htmlFor="name">Name <span className="text-gray-300 dark:text-gray-700">(local only)</span></label>
<NameField form={form} />
</div>
<Tabs.Root value={tab} onValueChange={setTab}>
<Tabs.Root className="mt-2" value={tab} onValueChange={setTab}>
<Tabs.List className="flex mb-4 border-b border-gray-300 dark:border-gray-700">
<Tooltip.Root>
<Tooltip.Trigger className="default-ring">
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/details/pages/PlanetDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export const PlanetDetails: React.FC = () => {
<label htmlFor="name">Name <span className="text-gray-300 dark:text-gray-700">(local only)</span></label>
<NameField form={form} />
</div>
<div>
<div className="mt-2">
<label htmlFor="shipname">Shipname <span className="text-gray-300 dark:text-gray-700">(Urbit ID)</span></label>
<ShipNameField form={form} />
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/details/pages/RemotePierDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export const RemotePierDetails = () => {
<label htmlFor="name">Name <span className="text-gray-300 dark:text-gray-700">(local only)</span></label>
<NameField form={form} />
</div>
<div>
<div className="mt-2">
<label htmlFor="directory">URL</label>
<div className="relative">
<input
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/details/pages/Star.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export const Star: React.FC = () => {
<label htmlFor="name">Name <span className="text-gray-300 dark:text-gray-700">(local only)</span></label>
<NameField form={form} />
</div>
<div>
<div className="mt-2">
<label htmlFor="shipname">Shipname <span className="text-gray-300 dark:text-gray-700">(Urbit ID)</span></label>
<ShipNameField form={form} />
</div>
Expand Down
7 changes: 7 additions & 0 deletions src/renderer/icons/Pencil.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import React from 'react'

export const Pencil = ({ className = '', primary = ''}: IconProps) => (
<svg xmlns="http://www.w3.org/2000/svg" className={className} viewBox="0 0 20 20" fill={primary}>
<path d="M13.586 3.586a2 2 0 112.828 2.828l-.793.793-2.828-2.828.793-.793zM11.379 5.793L3 14.172V17h2.828l8.38-8.379-2.83-2.828z" />
</svg>
)
5 changes: 3 additions & 2 deletions src/renderer/ship/Ship.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { Spinner } from '../shared/Spinner'
import { getCometShortName } from '../shared/urbit-utils'
import { ShipStatus } from './components/ShipStatus'
import { LaunchButton } from './components/LaunchButton'
import { EditableShipName } from './components/EditableShipName'
import { pierKey } from '../query-keys'
import { Pier } from '../../background/services/pier-service'
import { Dialog, DialogClose, DialogContent, DialogTrigger } from '../shared/Dialog'
Expand Down Expand Up @@ -85,8 +86,8 @@ export const Ship: React.FC = () => {
<header className="flex items-center">
<div className="mr-6">
<h1 className="font-semibold mb-1">
<span className="inline-block mr-2 text-xl text-black dark:text-white">{ ship.name }</span>
<span className="inline-block whitespace-nowrap">{ ship.type === 'comet' ? getCometShortName(ship.shipName || '') : ship.shipName }</span>
<EditableShipName ship={ship} />
<div className="mb-4 mt-2 whitespace-nowrap">{ ship.type === 'comet' ? getCometShortName(ship.shipName || '') : ship.shipName }</div>
</h1>
<div className="flex items-center">
<ShipStatus ship={ship} />
Expand Down
67 changes: 67 additions & 0 deletions src/renderer/ship/components/EditableShipName.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import React from 'react'
import { useForm } from 'react-hook-form'
import { useQueryClient, useMutation } from 'react-query'
import { pierKey } from "../../query-keys";
import { Pencil } from '../../icons/Pencil'
import { Close } from '../../icons/Close'
import { Pier, UpdatePier } from "../../../background/services/pier-service"
import { send } from '../../client/ipc'
import { NameField } from '../../details/components/NameField'

export const EditableShipName = (props: { ship: Pier }) => {
const [editMode, setEditMode] = React.useState(false)
const queryClient = useQueryClient()

const form = useForm<UpdatePier>({
mode: 'onChange',
reValidateMode: 'onChange',
defaultValues: {
name: props.ship.name
}
})
const { mutate } = useMutation((data: UpdatePier) => send('update-pier', {...props.ship, ...data}), {
onSuccess: (pier: Pier) => {
queryClient.setQueryData(pierKey(pier.slug), pier)
setEditMode(false)
}
})

const { isValid } = form.formState

const ShipNameDisplay = (
<div className="w-2/3 flex flex-row items-baseline">
<div className="mr-3 text-xl text-black dark:text-white whitespace-nowrap">{ props.ship.name }</div>
<button className="button opacity-70" onClick={setEditMode.bind(this, true)}>
<Pencil className="w-4 h-4 opacity-70" primary="gray"/>
</button>
</div>
)

const ShipNameEdit = (
<form onSubmit={form.handleSubmit((data) => mutate(data))}>
<div className="w-100 flex flex-row baseline">
<div className="w-2/3 mr-2 text-black dark:text-white">
<NameField form={form} />
</div>
<div className="relative">
<button className="button absolute top-2 font-semibold text-gray-300 dark:text-gray-700" type="submit" disabled={!isValid}>
Save
</button>
<button className="button absolute top-2 p-1.5 left-14" onClick={setEditMode.bind(this, false)}>
<Close className="w-4 h-4" primary="fill-current opacity-40" />
</button>
</div>
</div>
</form>
)

return (
<div className="w-100 flex flex-row items-baseline">
{
editMode
? ShipNameEdit
: ShipNameDisplay
}
</div>
)
}

0 comments on commit bb279aa

Please sign in to comment.