Skip to content

Commit

Permalink
adds autosubmit feature and renames component
Browse files Browse the repository at this point in the history
  • Loading branch information
josemigallas committed Feb 16, 2021
1 parent 8678f3e commit 790a89b
Show file tree
Hide file tree
Showing 15 changed files with 203 additions and 105 deletions.
2 changes: 1 addition & 1 deletion app/controllers/api/application_plans_controller.rb
Expand Up @@ -34,7 +34,7 @@ def destroy
end

def masterize
generic_masterize_plan(@service, :default_application_plan)
new_masterize_plan(@service, :default_application_plan)
end

protected
Expand Down
10 changes: 10 additions & 0 deletions app/controllers/api/plans_base_controller.rb
Expand Up @@ -112,6 +112,16 @@ def plans_index_path

protected

def new_masterize_plan(issuer, assoc)
if @plan.nil? || issuer.send(assoc) == @plan
issuer.send("#{assoc}=", nil)
else
issuer.send("#{assoc}=", @plan)
end

issuer.save!
end

def generic_masterize_plan(issuer, assoc)
masterize_plan do
if @plan.nil? || issuer.send(assoc) == @plan
Expand Down
21 changes: 14 additions & 7 deletions app/helpers/api/application_plans_helper.rb
Expand Up @@ -2,15 +2,22 @@

module Api::ApplicationPlansHelper

def application_plans_data
@plans.not_custom
.alphabetically
.to_json(root: false, only: %i[id name])
def default_plan_data(service, plans)
{
'current-service': service.to_json(root: false, only: %i[id name]),
'application-plans': application_plans_data(plans),
'current-plan': default_application_plan_data(service)
}
end

def current_plan_id_data
# -1 is the ID of the "select none" option in DefaultPlanSelector.jsx
@service.default_application_plan.try!(:id) || -1
def application_plans_data(plans)
plans.not_custom
.alphabetically
.to_json(root: false, only: %i[id name])
end

def default_application_plan_data(service)
service.default_application_plan&.to_json(root: false, only: %i[id name]) || nil.to_json
end

end
10 changes: 6 additions & 4 deletions app/javascript/packs/default_plan_selector.js
@@ -1,13 +1,15 @@
import { DefaultPlanSelectorWrapper } from 'Applications'
import { DefaultPlanSelectWrapper } from 'Applications'
import { safeFromJsonString } from 'utilities/json-utils'

document.addEventListener('DOMContentLoaded', () => {
const { dataset } = document.getElementById('default_plan')
const currentService = safeFromJsonString(dataset.currentService)
const plans = safeFromJsonString(dataset.applicationPlans)
const currentPlanId = Number(dataset.currentPlanId)
const currentPlan = safeFromJsonString(dataset.currentPlan) ?? undefined

DefaultPlanSelectorWrapper({
DefaultPlanSelectWrapper({
currentService,
plans,
currentPlanId
currentPlan
}, 'default_plan')
})
119 changes: 119 additions & 0 deletions app/javascript/src/Applications/components/DefaultPlanSelect.jsx
@@ -0,0 +1,119 @@
// @flow

import React, { useState, useEffect } from 'react'
import * as ajax from 'utilities/ajax'

import {
Form,
FormGroup,
PageSection,
PageSectionVariants,
Select,
SelectOption,
SelectVariant
} from '@patternfly/react-core'
import { PlanSelectOptionObject } from 'Applications'

import './DefaultPlanSelect.scss'

type Service = {
id: number,
name: string,
}

type ApplicationPlan = {
id: number,
name: string
}

type Props = {
currentService: Service,
currentPlan?: ApplicationPlan,
plans: ApplicationPlan[]
}

const NO_DEFAULT_PLAN: ApplicationPlan = { id: -1, name: '(No default plan)' }

// TODO: prevent reload screen when pressing Enter

const DefaultPlanSelect = ({ currentService, currentPlan = NO_DEFAULT_PLAN, plans }: Props) => {
const [selection, setSelection] = useState<PlanSelectOptionObject | null>(new PlanSelectOptionObject(currentPlan))
const [isExpanded, setIsExpanded] = useState(false)
const [isLoading, setIsLoading] = useState(false)

const onSelect = (_e, newPlan: PlanSelectOptionObject) => {
setSelection(newPlan)
setIsExpanded(false)
setIsLoading(true)

const body = newPlan.id >= 0 ? new URLSearchParams({ id: newPlan.id.toString() }) : undefined

// making request...
ajax.post(`/apiconfig/services/${currentService.id}/application_plans/masterize`, body)
.then(data => {
console.log(data)
if (data.ok) {
$.flash('Default plan was updated')
} else {
$.flash.error('Plan could not be updated')
}
})
.catch(err => {
console.error(err)
$.flash.error('An error ocurred. Please try again later.')
})
.finally(() => setIsLoading(false))
}

const onClear = () => {
setSelection(null)
}

useEffect(() => {
console.log(setIsLoading)
// console.log('Setting new default: ' + String(selection))
// setIsLoading(true)

// setTimeout(() => {
// setIsLoading(false)
// }, 500)
}, [selection])

const options = [NO_DEFAULT_PLAN, ...plans]
.filter(p => p.id !== currentPlan.id) // Don't show the current default plan
.map(p => new PlanSelectOptionObject(p))

return (
<PageSection variant={PageSectionVariants.light} className="pf-u-mb-md" id="default-plan-selector">
<Form onSubmit={e => e.preventDefault()}>
<FormGroup
label="Default plan"
fieldId="application_plan_id"
helperText="Default application plan (if any) is selected automatically upon service subscription."
>
<Select
variant={SelectVariant.typeahead}
aria-label="Select application plan"
placeholderText="Select application plan"
onToggle={() => setIsExpanded(!isExpanded)}
onSelect={onSelect}
onClear={onClear}
onKeyDown={e => {
console.log('pressed')
e.preventDefault()
}}
onBlur={() => console.log('blur')}
isExpanded={isExpanded}
isDisabled={isLoading}
selections={selection}
isCreatable={false}
>
{options.map(p => <SelectOption key={p.id} value={p} />)}
</Select>
</FormGroup>
</Form>
</PageSection>
)
}

export { DefaultPlanSelect }
@@ -0,0 +1,5 @@
#default-plan-selector {
.pf-c-select__toggle.pf-m-disabled input {
background-color: var(--pf-global--disabled-color--300);
}
}
@@ -0,0 +1,8 @@
import React from 'react'

import { DefaultPlanSelect } from 'Applications'
import { createReactWrapper } from 'utilities/createReactWrapper'

const DefaultPlanSelectWrapper = (props, containerId) => createReactWrapper(<DefaultPlanSelect {...props} />, containerId)

export { DefaultPlanSelectWrapper }
80 changes: 0 additions & 80 deletions app/javascript/src/Applications/components/DefaultPlanSelector.jsx

This file was deleted.

This file was deleted.

@@ -1,11 +1,16 @@
// @flow

import { SelectOptionObject } from '@patternfly/react-core'

type Plan = {
id: string,
id: number,
name: string
}

class PlanSelectOptionObject implements SelectOptionObject {
id: number
name: string

constructor (plan: Plan) {
this.id = plan.id
this.name = plan.name
Expand Down
4 changes: 2 additions & 2 deletions app/javascript/src/Applications/index.js
@@ -1,5 +1,5 @@
// @flow

export * from 'Applications/components/PlanSelectOptionObject'
export * from 'Applications/components/DefaultPlanSelector'
export * from 'Applications/components/DefaultPlanSelectorWrapper'
export * from 'Applications/components/DefaultPlanSelect'
export * from 'Applications/components/DefaultPlanSelectWrapper'
12 changes: 12 additions & 0 deletions app/javascript/src/utilities/ajax.js
@@ -0,0 +1,12 @@
// @flow

const post = (url: string, body?: URLSearchParams) => fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]').content
},
body
})

export { post }
3 changes: 2 additions & 1 deletion app/views/api/plans/_default_plan.html.slim
@@ -1,2 +1,3 @@
div id='default_plan' data-application-plans=(application_plans_data()) data-current-plan-id=(current_plan_id_data())
h1 New
div id='default_plan' data=default_plan_data(@service, @plans)
= javascript_pack_tag 'default_plan_selector'
2 changes: 1 addition & 1 deletion app/views/master/providers/plans/_widget.html.slim
Expand Up @@ -20,7 +20,7 @@ div.dashboard_card.round#provider-change-plan
br
= form_tag edit_master_provider_plan_path(provider), :method => :get, :remote => true, :class => 'formtastic colorbox' do
fieldset.inputs
legend Change Plan
legend Change Plan PEPE
ol
li
= select_tag :plan_id, options_from_collection_for_select(plans, :id, :name), required: true, include_blank: true
Expand Down
@@ -0,0 +1,17 @@
// @flow

import React from 'react'

import { DefaultPlanSelect } from 'Applications'
import { mount } from 'enzyme'

const props = {
currentService: { id: 0, name: 'Le Service' },
currentPlan: undefined,
plans: []
}

it('should render', () => {
const wrapper = mount(<DefaultPlanSelect {...props} />)
expect(wrapper.exists()).toBe(true)
})

0 comments on commit 790a89b

Please sign in to comment.