diff --git a/app/controllers/api/protocols_controller.rb b/app/controllers/api/protocols_controller.rb index 832a1b4..16b6742 100644 --- a/app/controllers/api/protocols_controller.rb +++ b/app/controllers/api/protocols_controller.rb @@ -1,6 +1,6 @@ class Api::ProtocolsController < ApplicationController expose :protocols, -> { Protocol.includes_associated.all } - expose :protocol + expose :protocol, id: -> { params[:slug] }, find_by: :slug skip_before_action :authenticate_user!, only: [:execute] diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index d760a83..98ea1a7 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -53,7 +53,7 @@ def currencies Monetize::Parser::CURRENCY_SYMBOLS.map { |sym, abbr| { symbol: sym, code: abbr } } end - def after_sign_in_path_for(_resouce) + def after_sign_in_path_for(_) screens_path end diff --git a/app/controllers/screens_controller.rb b/app/controllers/screens_controller.rb index fa2934c..9ab71cb 100644 --- a/app/controllers/screens_controller.rb +++ b/app/controllers/screens_controller.rb @@ -60,7 +60,7 @@ def create def update authorize screen if screen.update(screen_params) - redirect_to screen, notice: "Screen was successfully updated." + redirect_to edit_screen_path(screen.slug), notice: "Screen was successfully updated." else redirect_to edit_screen_path, inertia: { errors: screen.errors } end @@ -70,7 +70,7 @@ def update def destroy authorize screen screen.destroy! - redirect_to screens_url, notice: "Screen was successfully destroyed." + redirect_to edit_screens_path, notice: "Screen was successfully destroyed." end private diff --git a/app/controllers/users/sessions_controller.rb b/app/controllers/users/sessions_controller.rb index fcd9ecd..aa59cb4 100644 --- a/app/controllers/users/sessions_controller.rb +++ b/app/controllers/users/sessions_controller.rb @@ -15,7 +15,7 @@ def create self.resource = warden.authenticate!(auth_options) sign_in(resource_name, resource) yield resource if block_given? - respond_with resource, location: after_sign_in_path_for(resource) + respond_with resource, location: session[:user_return_to] || after_sign_in_path_for(resource) end # @route GET /logout (destroy_user_session) diff --git a/app/frontend/Components/Button/DeleteButton.tsx b/app/frontend/Components/Button/DeleteButton.tsx index 692175f..fadac7d 100644 --- a/app/frontend/Components/Button/DeleteButton.tsx +++ b/app/frontend/Components/Button/DeleteButton.tsx @@ -4,10 +4,15 @@ import { type LinkProps } from '../Link' import { TrashIcon } from '@/Components/Icons' interface IDeleteButtonProps extends Omit { + children?: string label?: string } -const DeleteButton = ({ href, label, ...props }: IDeleteButtonProps) => { +const DeleteButton = ({ children, href, label, onClick, ...props }: IDeleteButtonProps) => { + const handleClick = (e: React.SyntheticEvent) => { + onClick?.(e) + } + return ( { method="delete" href={ href } aria-label={ `Delete ${label}` } + onClick={ handleClick } { ...props } > - + { children } ) } diff --git a/app/frontend/Components/Form/Form.tsx b/app/frontend/Components/Form/Form.tsx index bcb0afe..76ebe65 100644 --- a/app/frontend/Components/Form/Form.tsx +++ b/app/frontend/Components/Form/Form.tsx @@ -38,6 +38,7 @@ const Form = ({ data={ data } className={ cx({ 'format-grid': !disableFormatting }, className) } railsAttributes={ railsAttributes } + remember={ false } { ...props } > { children } diff --git a/app/frontend/Components/Link/InertiaLink.tsx b/app/frontend/Components/Link/InertiaLink.tsx index 7cdded3..5dc3620 100644 --- a/app/frontend/Components/Link/InertiaLink.tsx +++ b/app/frontend/Components/Link/InertiaLink.tsx @@ -17,7 +17,18 @@ interface LinkProps extends AnchorLinkProps { } const InertiaLinkComponent = forwardRef(( - { children, href, as = 'a', method, visit, buttonProps, style, disabled, ...props }, + { + children, + href, + as = 'a', + method, + visit, + buttonProps, + style, + disabled, + onClick, + ...props + }, ref, ) => { const handleHTTP = (e: React.MouseEvent) => { @@ -27,9 +38,15 @@ const InertiaLinkComponent = forwardRef(( method, ...visit, }) + + onClick?.(e) } - const mergedButtonProps = Object.assign({ disabled }, buttonProps, exclude(props, ['classNames', 'styles', 'vars'])) + const mergedButtonProps = Object.assign( + { disabled }, + exclude(buttonProps, 'onClick'), + exclude(props, ['classNames', 'styles', 'vars', 'onClick']), + ) const processedHref = disabled ? '#' : href diff --git a/app/frontend/Components/Link/index.tsx b/app/frontend/Components/Link/index.tsx index 7b6f038..7d5dcd4 100644 --- a/app/frontend/Components/Link/index.tsx +++ b/app/frontend/Components/Link/index.tsx @@ -49,7 +49,6 @@ const Link = forwardRef(( onClick?.(e) return false } - return onClick?.(e) } diff --git a/app/frontend/Components/index.ts b/app/frontend/Components/index.ts index 0318b8a..9752af8 100644 --- a/app/frontend/Components/index.ts +++ b/app/frontend/Components/index.ts @@ -12,6 +12,7 @@ export { default as Tabs } from './Tabs' // Export UI library components as a proxy to allow easy refactoring export { + Accordion, ActionIcon, Affix, AppShell, diff --git a/app/frontend/Features/Control/Form.tsx b/app/frontend/Features/Control/Form.tsx index 2260c62..f1f4c67 100644 --- a/app/frontend/Features/Control/Form.tsx +++ b/app/frontend/Features/Control/Form.tsx @@ -14,10 +14,10 @@ export interface ControlFormProps extends Omit, 'data } const ControlForm = ({ control, ...props }: ControlFormProps) => { - const [showingProtocolSlug, setShowingProtocolSlug] = useState(control?.protocol?.slug) + const [showingProtocolSlug, setShowingProtocolSlug] = useState(control?.protocol?.slug || '') const { data } = useGetProtocol({ slug: showingProtocolSlug }, { - initialData: control?.protocol, + initialData: control?.protocol || {}, enabled: !!showingProtocolSlug, }) diff --git a/app/frontend/Pages/Screens/Edit/EditControls/DraggableControl.tsx b/app/frontend/Pages/Screens/Edit/EditControls/DraggableControl.tsx index 4e03a48..0a71e26 100644 --- a/app/frontend/Pages/Screens/Edit/EditControls/DraggableControl.tsx +++ b/app/frontend/Pages/Screens/Edit/EditControls/DraggableControl.tsx @@ -7,6 +7,7 @@ import EditControlButton from './EditControlButton' import cx from 'clsx' import * as classes from './Control.css' +import { router } from '@inertiajs/react' interface DraggableControlProps extends ControlProps<{edit: true}> {} @@ -32,6 +33,7 @@ const DraggableControl = ({ control, ...props }: DraggableControlProps) => { > router.reload() } /> void +} + +const EditScreenTabButton = ({ screen, onSuccess, ...props }: EditScreenTabButtonProps) => { + + const handleEditButtonClick = (e: React.MouseEvent) => { + e.stopPropagation() + e.preventDefault() + + modals.open({ + title: 'Edit Screen', + children: ( + <> + modals.closeAll() } + /> + + + + Permanently Delete + + Will permanently delete this screen and all controls on the screen + modals.closeAll() } + > + Delete + + + + + + ), + }) + } + + return ( + + + + ) +} + +export default EditScreenTabButton diff --git a/app/frontend/Pages/Screens/Edit/ScreenTabControls/NewScreenTabButton.tsx b/app/frontend/Pages/Screens/Edit/ScreenTabControls/NewScreenTabButton.tsx new file mode 100644 index 0000000..ba198b9 --- /dev/null +++ b/app/frontend/Pages/Screens/Edit/ScreenTabControls/NewScreenTabButton.tsx @@ -0,0 +1,30 @@ +import React from 'react' +import { Button } from '@/Components' +import { modals } from '@mantine/modals' +import ScreenForm from '../../Form' +import { Routes } from '@/lib' + +const NewScreenTabButton = () => { + + const handleNewScreenModalTrigger = () => { + modals.open({ + title: 'Create a New Screen', + children: ( + modals.closeAll() } + /> + ), + }) + } + + return ( + + ) +} + +export default NewScreenTabButton diff --git a/app/frontend/Pages/Screens/Edit/index.tsx b/app/frontend/Pages/Screens/Edit/index.tsx index 6f692cf..70adf09 100644 --- a/app/frontend/Pages/Screens/Edit/index.tsx +++ b/app/frontend/Pages/Screens/Edit/index.tsx @@ -1,14 +1,14 @@ import React, { useState } from 'react' -import { Button, Divider, Page, Tabs } from '@/Components' +import { Divider, Page, Tabs } from '@/Components' import { Form, Submit } from '@/Components/Form' import { Routes } from '@/lib' import { useLocation } from '@/lib/hooks' import { router } from '@inertiajs/react' import { useDroppable } from '@dnd-kit/core' import EditControls from './EditControls' -import { modals } from '@mantine/modals' -import ScreenForm from '../Form' import NewControlMenu from './NewControlMenu' +import NewScreenTabButton from './ScreenTabControls/NewScreenTabButton' +import EditScreenTabButton from './ScreenTabControls/EditScreenTabButton' import cx from 'clsx' import * as classes from './ScreenControl.css' @@ -38,18 +38,6 @@ const EditScreen = ({ screen, screens }: IEditScreenProps) => { id: 'screen_droppable', }) - const handleNewScreenModalTrigger = () => { - modals.open({ - title: 'Create a New Screen', - children: ( - modals.closeAll() } - /> - ), - }) - } - const handleTabChange = (value: string | null) => { if(value === null) return @@ -70,21 +58,20 @@ const EditScreen = ({ screen, screens }: IEditScreenProps) => { variant="outline" value={ paths[1] } onChange={ handleTabChange } + className={ cx(classes.tabsParent) } > { screens.map(iScreen => ( { iScreen.title } + )) } - + diff --git a/app/frontend/types/serializers/Protocols/Show.d.ts b/app/frontend/types/serializers/Protocols/Show.d.ts index cc3bf90..bb6f19b 100644 --- a/app/frontend/types/serializers/Protocols/Show.d.ts +++ b/app/frontend/types/serializers/Protocols/Show.d.ts @@ -1,4 +1,4 @@ -// TypesFromSerializers CacheKey 769c08a77763c163f07ddf9ff5ddffbc +// TypesFromSerializers CacheKey 51d92a1c0febda98424763bb16972478 // // DO NOT MODIFY: This file was automatically generated by TypesFromSerializers. import type ProtocolsCommands from './Commands' @@ -8,11 +8,9 @@ declare global { interface ProtocolsShow { id: number commands: ProtocolsCommands[] - created_at: string | Date description?: string slug: string title: string - updated_at: string | Date } } } diff --git a/app/models/screen.rb b/app/models/screen.rb index fa7d1e5..d6db9c2 100644 --- a/app/models/screen.rb +++ b/app/models/screen.rb @@ -24,6 +24,7 @@ class Screen < ApplicationRecord trigram: {} }, ) + self.implicit_order_column = "order" before_validation :set_screen_order @@ -33,6 +34,7 @@ class Screen < ApplicationRecord has_many :controls, -> { order(order: :asc) }, dependent: :nullify, inverse_of: :screen + default_scope { order(:order) } scope :includes_associated, -> { includes([:controls]) } validates :title, format: { without: /new/ } diff --git a/app/serializers/protocols/show_serializer.rb b/app/serializers/protocols/show_serializer.rb index e704575..47a4938 100644 --- a/app/serializers/protocols/show_serializer.rb +++ b/app/serializers/protocols/show_serializer.rb @@ -2,8 +2,6 @@ class Protocols::ShowSerializer < ProtocolSerializer attributes( :id, :slug, - :updated_at, - :created_at, ) has_many :commands, serializer: Protocols::CommandsSerializer diff --git a/config/environments/development.rb b/config/environments/development.rb index 19f981c..58e1aaa 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -61,7 +61,7 @@ # Highlight code that enqueued background job in logs. config.active_job.verbose_enqueue_logs = true - config.log_level = :warn + # config.log_level = :warn # Suppress logger output for asset requests. # config.assets.quiet = true