Skip to content
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

13309 Add ability to clear LU form dropdowns #866

Merged
merged 5 commits into from Nov 17, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion client/app/components/packages/applicant-fieldset.hbs
Expand Up @@ -84,7 +84,7 @@
</label>
</div>

<div class="cell auto medium-2">
<div class="cell auto medium-4">
<label data-test-applicant-state-dropdown>
State
<PowerSelect
Expand All @@ -95,6 +95,7 @@
@searchField="label"
@options={{map-by 'code' (optionset 'applicant' 'dcpState' 'list')}}
@onChange={{fn (mut @applicant.dcpState)}}
@allowClear={{true}}
as |stateCode|>
{{optionset 'applicant' 'dcpState' 'label' stateCode}}
</PowerSelect>
Expand Down
50 changes: 32 additions & 18 deletions client/app/components/packages/landuse-form/lead-agency.hbs
@@ -1,23 +1,37 @@
{{#let @landuseForm as |landuseForm|}}
<div>
<h5 class="small-margin-bottom">
Who is the lead agency?
</h5>
<div class="grid-x">
<div class="cell small-12">
<h5 class="small-margin-bottom">
Who is the lead agency?
</h5>

<label data-test-lead-agency-picker>
<PowerSelect
triggerClass="lead-agency-dropdown"
supportsDataTestProperties={{true}}
@placeholder={{this.searchPlaceholder}}
@searchEnabled={{true}}
@options={{this.accountNames}}
@selected={{this.chosenAccountName}}
@onChange={{fn (mut this.chosenAccountName)}}
@onClose={{fn (mut landuseForm.data.chosenLeadAgencyId) this.chosenAccountId}}
as |accountName|
<label data-test-lead-agency-picker>
{{!-- REDO: Rework this powerselect to act on Models,
the "Ember" way. Remove use of chosenAccountName --}}
<PowerSelect
triggerClass="lead-agency-dropdown"
supportsDataTestProperties={{true}}
@placeholder="Search agencies..."
@searchEnabled={{true}}
@options={{this.accountNames}}
@selected={{this.chosenAccountName}}
@onChange={{fn (mut this.chosenAccountName)}}
@onClose={{fn (mut landuseForm.data.chosenLeadAgencyId) this.chosenAccountId}}
as |accountName|
>
{{accountName}}
</PowerSelect>
</label>
</div>

<div class="cell text-right">
<button
type="button"
class="dropdown-clear-btn-below"
{{on "click" (fn this.clearDropdown landuseForm.data)}}
>
{{accountName}}
</PowerSelect>
</label>
Clear
</button>
</div>
</div>
{{/let}}
18 changes: 10 additions & 8 deletions client/app/components/packages/landuse-form/lead-agency.js
@@ -1,23 +1,25 @@
import Component from '@glimmer/component';
import { action } from '@ember/object';
import { tracked } from '@glimmer/tracking';

export default class PackagesLanduseFormLeadAgencyComponent extends Component {
@tracked chosenAccountName;
@tracked chosenAccountName = this.args.landuseForm.data.leadAgency ? this.args.landuseForm.data.leadAgency.name : null;
godfreyyeung marked this conversation as resolved.
Show resolved Hide resolved

get accountNames() {
if (this.args.accounts) {
return this.args.accounts.map((account) => account.name);
} return [];
}

get searchPlaceholder() {
if (this.args.landuseForm.data.leadAgency) {
return this.args.landuseForm.data.leadAgency.name;
} return 'Search agencies...';
}

get chosenAccountId() {
const account = this.args.accounts.find((account) => account.name === this.chosenAccountName);
return account.id;
return account ? account.id : null;
}

@action
clearDropdown(landuseFormData) {
this.chosenAccountName = null;
landuseFormData.chosenLeadAgencyId = null;
landuseFormData.leadAgency = null;
}
}
Expand Up @@ -178,26 +178,38 @@

{{/if}}

<div>
<h5 class="small-margin-bottom">
If this is a follow-up Action, indicate the previously approved Action Code
</h5>

<label data-test-dcpPreviouslyapprovedactioncode-picker="{{landuseActionForm.data.dcpActioncode}}">
<PowerSelect
triggerClass="previouslyapprovedactions-dropdown"
supportsDataTestProperties={{true}}
@placeholder={{this.selectedActionPlaceholder}}
@searchEnabled={{false}}
@options={{optionset 'landuseAction' 'dcpPreviouslyapprovedactioncode' 'list'}}
@selected={{this.actionCode}}
@onChange={{fn (mut this.actionCode)}}
@onClose={{fn this.setPreviouslyApprovedActionCodeFields this.actionCode.code}}
as |landUseAction|
<div class="grid-x">
<div class="cell small-12">
<h5 class="small-margin-bottom">
If this is a follow-up Action, indicate the previously approved Action Code
</h5>

<label data-test-dcpPreviouslyapprovedactioncode-picker="{{landuseActionForm.data.dcpActioncode}}">
<PowerSelect
triggerClass="previouslyapprovedactions-dropdown"
supportsDataTestProperties={{true}}
@placeholder="-- select an action --"
@searchEnabled={{false}}
@options={{optionset 'landuseAction' 'dcpPreviouslyapprovedactioncode' 'list'}}
@selected={{this.chosenDcpPreviouslyapprovedactioncode}}
@onChange={{fn (mut this.chosenDcpPreviouslyapprovedactioncode)}}
@onClose={{fn this.setPreviouslyApprovedActionCodeFields this.chosenDcpPreviouslyapprovedactioncode.code}}
as |landUseAction|
>
{{landUseAction.label}}
</PowerSelect>
</label>
</div>

<div class="cell text-right">
<button
type="button"
class="dropdown-clear-btn-below"
{{on "click" (fn this.clearPreviouslyApprovedActionCodeDropdown landuseActionForm.data)}}
>
{{landUseAction.label}}
</PowerSelect>
</label>
Clear
</button>
</div>
</div>

{{#if this.projectHasRequiredActionsAndFollowUpYes}}
Expand Down
@@ -1,9 +1,14 @@
import Component from '@glimmer/component';
import { action } from '@ember/object';
import { tracked } from '@glimmer/tracking';
import { optionset } from '../../../helpers/optionset';

export default class PackagesLanduseFormProposedActionEditorComponent extends Component {
actionCode;
@tracked chosenDcpPreviouslyapprovedactioncode = this.args.landuseActionForm.data.dcpPreviouslyapprovedactioncode
godfreyyeung marked this conversation as resolved.
Show resolved Hide resolved
? {
code: this.args.landuseActionForm.data.dcpPreviouslyapprovedactioncode,
label: optionset(['landuseAction', 'dcpPreviouslyapprovedactioncode', 'label', this.args.landuseActionForm.data.dcpPreviouslyapprovedactioncode]),
} : null;
godfreyyeung marked this conversation as resolved.
Show resolved Hide resolved

requiredActionCodes = ['CM', 'LD', 'RA', 'RC', 'RS', 'SA', 'SC', 'SD', 'ZA', 'ZC', 'ZS'];

Expand All @@ -17,20 +22,21 @@ export default class PackagesLanduseFormProposedActionEditorComponent extends Co
return this.projectHasRequiredActions && hasPreviousAction;
}

get selectedActionPlaceholder() {
const previouslyApprovedActionCode = this.args.landuseActionForm.data.dcpPreviouslyapprovedactioncode;
if (previouslyApprovedActionCode) {
return optionset(['landuseAction', 'dcpPreviouslyapprovedactioncode', 'label', previouslyApprovedActionCode]);
} return '-- select an action --';
}

@action
setPreviouslyApprovedActionCodeFields(actionCode) {
if (actionCode) {
this.args.landuseActionForm.data.dcpPreviouslyapprovedactioncode = actionCode;
this.args.landuseActionForm.data.dcpFollowuptopreviousaction = true;
} else if (!actionCode && !this.args.landuseActionForm.data.dcpPreviouslyapprovedactioncode) {
} else {
this.args.landuseActionForm.data.dcpPreviouslyapprovedactioncode = null;
this.args.landuseActionForm.data.dcpFollowuptopreviousaction = false;
}
}

@action
clearPreviouslyApprovedActionCodeDropdown(landuseActionFormData) {
this.chosenDcpPreviouslyapprovedactioncode = null;
landuseActionFormData.dcpPreviouslyapprovedactioncode = null;
landuseActionFormData.dcpFollowuptopreviousaction = false;
}
}
Expand Up @@ -37,6 +37,7 @@
@placeholder="-- select --"
@options={{map-by 'code' (optionset 'zoningMapChange' 'dcpExistingzoningdistrictvalue' 'list')}}
@onChange={{fn (mut form.data.dcpExistingzoningdistrictvalue)}}
@allowClear={{true}}
as |dcpExistingzoningdistrictvalue|>
{{optionset 'zoningMapChange' 'dcpExistingzoningdistrictvalue' 'label' dcpExistingzoningdistrictvalue}}
</PowerSelect>
Expand Down
Expand Up @@ -27,6 +27,7 @@
@placeholder="-- select --"
@options={{map-by 'code' (optionset 'landuseForm' 'dcpTotalzoningareatoberezoned' 'list')}}
@onChange={{fn (mut form.data.dcpTotalzoningareatoberezoned)}}
@allowClear={{true}}
as |dcpTotalzoningareatoberezoned|>
{{optionset 'landuseForm' 'dcpTotalzoningareatoberezoned' 'label' dcpTotalzoningareatoberezoned}}
</PowerSelect>
Expand Down
@@ -1,24 +1,36 @@
{{#let @landuseActionForm as |landuseActionForm|}}
<div>
<h5 class="small-margin-bottom">
What Zoning Resolution section is this Action pursuant to?
</h5>
<div class="grid-x">
<div class="cell small-12">
<h5 class="small-margin-bottom">
What Zoning Resolution section is this Action pursuant to?
</h5>

<label data-test-zoning-resolution-picker="{{landuseActionForm.data.dcpActioncode}}">
<PowerSelect
triggerClass="zoning-resolution-dropdown"
supportsDataTestProperties={{true}}
@placeholder={{this.searchPlaceholder}}
@searchEnabled={{true}}
@searchField="dcpZoningresolution"
@options={{@zoningResolutions}}
@selected={{this.chosenZoningResolution}}
@onChange={{fn (mut this.chosenZoningResolution)}}
@onClose={{fn (mut landuseActionForm.data.chosenZoningResolutionId) this.chosenZoningResolution.id}}
as |zoningResolution|
<label data-test-zoning-resolution-picker="{{landuseActionForm.data.dcpActioncode}}">
<PowerSelect
triggerClass="zoning-resolution-dropdown"
supportsDataTestProperties={{true}}
@placeholder="Search Zoning Resolution Sections..."
@searchEnabled={{true}}
@searchField="dcpZoningresolution"
@options={{@zoningResolutions}}
@selected={{this.chosenZoningResolution}}
@onChange={{fn (mut this.chosenZoningResolution)}}
@onClose={{fn (mut landuseActionForm.data.chosenZoningResolutionId) this.chosenZoningResolution.id}}
as |zoningResolution|
>
{{zoningResolution.dcpZoningresolution}}
</PowerSelect>
</label>
</div>

<div class="cell text-right">
<button
type="button"
class="dropdown-clear-btn-below"
{{on "click" (fn this.clearDropdown landuseActionForm.data)}}
>
{{zoningResolution.dcpZoningresolution}}
</PowerSelect>
</label>
Clear
</button>
</div>
</div>
{{/let}}
@@ -1,12 +1,14 @@
import Component from '@glimmer/component';
import { action } from '@ember/object';
import { tracked } from '@glimmer/tracking';

export default class PackagesLanduseFormZoningResolutionComponent extends Component {
@tracked chosenZoningResolution;
@tracked chosenZoningResolution = this.args.landuseActionForm.data.zoningResolution || null;
godfreyyeung marked this conversation as resolved.
Show resolved Hide resolved

get searchPlaceholder() {
if (this.args.landuseActionForm.data.zoningResolution) {
return this.args.landuseActionForm.data.zoningResolution.dcpZoningresolution;
} return 'Search Zoning Resolution Sections...';
@action
clearDropdown(landuseActionFormData) {
this.chosenZoningResolution = null;
landuseActionFormData.zoningResolution = null;
landuseActionFormData.chosenZoningResolutionId = null;
}
}
6 changes: 6 additions & 0 deletions client/app/styles/app.scss
Expand Up @@ -165,3 +165,9 @@ $sticky-sidebar-offset: 6rem + rem-calc(20);
font-size: rem-calc(13);
margin-bottom: 0.25 * $global-margin;
}

// Companion custom "Clear" button
// Sits below a dropdown, aligned right
.dropdown-clear-btn-below {
color: $red-dark;
}
5 changes: 5 additions & 0 deletions client/app/styles/modules/_powerselect-overrides.scss
Expand Up @@ -49,3 +49,8 @@
border: $input-border-focus;
}
}

.ember-power-select-clear-btn {
top: 5px;
right: 35px;
}
9 changes: 9 additions & 0 deletions server/src/crm/crm.service.ts
Expand Up @@ -82,6 +82,10 @@ export class CrmService {
return this._associate(relationshipName, entitySetName1, guid1, entitySetName2, guid2, headers);
}

async disassociateHasOne(singleValuedNavigationProperty, entitySetName, guid) {
return this._disassociateSingleValuedNavigationProperty(singleValuedNavigationProperty, entitySetName, guid);
}

godfreyyeung marked this conversation as resolved.
Show resolved Hide resolved
/**
* Makes a CRM Web API query using the passed in query in XML format
*
Expand Down Expand Up @@ -401,6 +405,11 @@ export class CrmService {
return this.create(query, data, headers);
}

async _disassociateSingleValuedNavigationProperty(singleValuedNavigationProperty, entitySetName, guid) {
godfreyyeung marked this conversation as resolved.
Show resolved Hide resolved
const query = entitySetName + "(" + guid + ")/" + singleValuedNavigationProperty + "/$ref";
return this._sendDeleteRequest(query, {});
}

async generateSharePointAccessToken(): Promise<any> {
const TENANT_ID = this.config.get('TENANT_ID');
const SHAREPOINT_CLIENT_ID = this.config.get('SHAREPOINT_CLIENT_ID');
Expand Down
Expand Up @@ -28,15 +28,30 @@ export class LanduseActionsController {

@Patch('/:id')
async update(@Body() body, @Param('id') id) {
const allowedAttrs = pick(body, LANDUSE_ACTION_ATTRS);
let allowedAttrs = pick(body, LANDUSE_ACTION_ATTRS);
const dateOfPreviousApproval = this.pickDate(body.dcp_dateofpreviousapproval);
const lapseDateOfPreviousApproval = this.pickDate(body.dcp_lapsedateofpreviousapproval);
const recordationDate = this.pickDate(body.dcp_recordationdate);

// "chosen_zoning_resolution_id" is the id to a related resource,
// but, unlike other attributes, it may not always be included
// in the request body.
// If a request does not include all of the relationships
// for a resource, the server MUST interpret the missing relationships
// as if they were included with their current values. It MUST NOT
// interpret them as null or empty values.
// Therefore, we explicitly check for a null value
// (which would imply a key for chosen_zoning_resolution_id),
// to avoid assuming that falsiness indicates a disassociation.
if (body.chosen_zoning_resolution_id) {
godfreyyeung marked this conversation as resolved.
Show resolved Hide resolved
allowedAttrs['dcp_zoningresolutionsectionactionispursuantto@odata.bind'] = `/dcp_zoningresolutions(${body.chosen_zoning_resolution_id})`;
godfreyyeung marked this conversation as resolved.
Show resolved Hide resolved
} else if (body.chosen_zoning_resolution_id === null) {
await this.crmService.disassociateHasOne('dcp_zoningresolutionsectionactionispursuantto', 'dcp_landuseactions', id);
}

await this.crmService.update('dcp_landuseactions', id, {
...allowedAttrs,

...(body.chosen_zoning_resolution_id ? { 'dcp_zoningresolutionsectionactionispursuantto@odata.bind': `/dcp_zoningresolutions(${body.chosen_zoning_resolution_id})` } : {}),
dcp_dateofpreviousapproval: dateOfPreviousApproval,
dcp_lapsedateofpreviousapproval: lapseDateOfPreviousApproval,
dcp_recordationdate: recordationDate,
Expand Down