Skip to content
This repository has been archived by the owner on Jul 26, 2024. It is now read-only.

Commit

Permalink
Merge branch 'enhancement/add-salary-data-block' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
admturner committed Sep 1, 2022
2 parents 91faa17 + 9118e02 commit b86b44b
Show file tree
Hide file tree
Showing 12 changed files with 669 additions and 0 deletions.
1 change: 1 addition & 0 deletions inc/blocks.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
// Include files required for dynamic block registration.
require plugin_dir_path( dirname( __FILE__ ) ) . 'build/blocks/posts-list/index.php';
require plugin_dir_path( dirname( __FILE__ ) ) . 'build/blocks/list-awards/index.php';
require plugin_dir_path( dirname( __FILE__ ) ) . 'build/blocks/salary-data/index.php';

/**
* Registers HRSWP blocks.
Expand Down
1 change: 1 addition & 0 deletions src/blocks/editor.css
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@
@import "./list-awards/editor.css";
@import "./notification/editor.css";
@import "./posts-list/editor.css";
@import "./salary-data/editor.css";
@import "./sidebar/editor.css";
2 changes: 2 additions & 0 deletions src/blocks/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import * as callout from './callout';
import * as notification from './notification';
import * as sidebar from './sidebar';
import * as listAwards from './list-awards';
import * as salaryData from './salary-data';

const hrsBlocks = [
accordionHeading,
Expand All @@ -33,6 +34,7 @@ const hrsBlocks = [
notification,
sidebar,
listAwards,
salaryData,
];

const hiddenBlocks = [
Expand Down
25 changes: 25 additions & 0 deletions src/blocks/salary-data/block.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"apiVersion": 2,
"name": "hrswp/salary-data",
"title": "HRS Salary Data",
"category": "hrswp-blocks-external",
"description": "Display WSU salary data.",
"textdomain": "default",
"attributes": {
"queryTable": {
"type": "string"
}
},
"supports": {
"align": true,
"html": false
},
"styles": [
{
"name": "default",
"label": "Default",
"isDefault": true
},
{ "name": "stripes", "label": "Stripes" }
]
}
161 changes: 161 additions & 0 deletions src/blocks/salary-data/edit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
/**
* External dependencies
*/
import { unescape } from 'lodash';

/**
* WordPress dependencies
*/
import {
PanelBody,
Placeholder,
SelectControl,
Spinner,
} from '@wordpress/components';
import { dispatch, useSelect } from '@wordpress/data';
import { InspectorControls, useBlockProps } from '@wordpress/block-editor';
import { __ } from '@wordpress/i18n';

/**
* Internal dependencies
*/
import { RenderNursesYearsExperienceRow } from './nurses-experience-row';

export default function SalaryDataEdit( {
attributes: { queryTable },
setAttributes,
} ) {
const { salaryData, isRequesting, tables } = useSelect(
( select ) => {
const { getSalaryData, getTableNames, isResolving } =
select( 'hrswp/blocks' );

return {
salaryData: queryTable?.length
? getSalaryData( queryTable )
: {},
isRequesting: isResolving( 'getSalaryData', [ queryTable ] ),
tables: getTableNames(),
};
},
[ queryTable ]
);

const toggleAttribute = ( attributeName ) => ( newValue ) => {
if ( 'queryTable' === attributeName ) {
dispatch( 'hrswp/blocks' ).invalidateResolutionForStoreSelector(
'getSalaryData'
);
}
setAttributes( { [ attributeName ]: newValue } );
};
const getQueryTables = () => {
if ( ! tables?.length ) {
return [];
}
return tables?.reduce( ( accumulator, currentValue ) => {
if (
currentValue.value.includes( 'salary' ) ||
'' === currentValue.value
) {
accumulator.push( currentValue );
}
return accumulator;
}, [] );
};
const formatNumber = new Intl.NumberFormat( 'en-US', {
style: 'currency',
currency: 'USD',
maximumFractionDigits: 0,
} );

const renderJobClassificationName = ( name ) =>
! name ? __( '(Untitled)' ) : unescape( name ).trim();
const renderJobClassificationCurrency = ( number ) =>
! Number.isNaN( Number( number ) )
? formatNumber.format( number )
: renderJobClassificationName( number );

const renderSalaryDataTable = () => {
return (
<figure className="wp-block-table">
<table>
<thead>
<tr>
{ Object.keys( salaryData[ 0 ] ).map(
( salaryKey, index ) =>
renderSalaryDataTableHeaderRow(
salaryKey,
index
)
) }
</tr>
{ queryTable.includes( 'nurses' ) &&
RenderNursesYearsExperienceRow( queryTable ) }
</thead>
<tbody>
{ salaryData.map( ( salary, index ) =>
renderSalaryDataTableRow( salary, index )
) }
</tbody>
</table>
</figure>
);
};

const renderSalaryDataTableHeaderRow = ( salaryKey, index ) => {
const headValue =
'RANGE' !== salaryKey
? `Step ${ renderJobClassificationName( salaryKey ) }`
: 'Range';
return <th key={ index }>{ headValue }</th>;
};

const renderSalaryDataTableRow = ( salary, index ) => {
return (
<tr key={ index }>
{ Object.entries( salary ).map( ( entry, i ) => {
const [ key, value ] = entry;
const cell =
'RANGE' !== key
? renderJobClassificationCurrency( value )
: renderJobClassificationName( value );
return <td key={ i }>{ cell }</td>;
} ) }
</tr>
);
};

return (
<div { ...useBlockProps() }>
<InspectorControls>
<PanelBody title={ __( 'Salary Data settings' ) }>
<SelectControl
className={ 'salary-data-table-picker__select' }
label={ __( 'Select Job Data source' ) }
value={ queryTable }
options={ getQueryTables() }
onChange={ toggleAttribute( 'queryTable' ) }
/>
</PanelBody>
</InspectorControls>
{ ! queryTable && (
<Placeholder icon="admin-post" label={ __( 'Salary Data' ) }>
{ ! Array.isArray( tables ) ? (
<Spinner />
) : (
__( 'Select a salary data group to display results.' )
) }
</Placeholder>
) }
{ queryTable && isRequesting && (
<Placeholder icon="admin-post" label={ __( 'Salary Data' ) }>
<Spinner />
</Placeholder>
) }
{ ! isRequesting &&
salaryData?.length > 0 &&
renderSalaryDataTable() }
</div>
);
}
35 changes: 35 additions & 0 deletions src/blocks/salary-data/editor.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
.wp-block-hrswp-salary-data {

& .wp-block-table table {
border-spacing: 0;
font-variant-numeric: lining-nums tabular-nums;
margin-bottom: 1.5rem;
width: 100%;

& thead {
border-bottom: none;
}

& td,
& th {
border: none;
padding: 0.45em;
text-align: left;
}

& th {
background-color: var(--wp--custom--wsu-color-black--10);
font-weight: 600;
}

& tbody tr {
border-bottom: 1px solid var(--wp--custom--wsu-color-black--20);
}

}

&.is-style-stripes .wp-block-table tbody tr:nth-child(2n+1) {
background: var(--wp--custom--wsu-color-black--3);
}

}
10 changes: 10 additions & 0 deletions src/blocks/salary-data/icon.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/**
* WordPress dependencies
*/
import { Path, SVG } from '@wordpress/components';

export default (
<SVG xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<Path d="M3.25 12a8.75 8.75 0 1117.5 0 8.75 8.75 0 01-17.5 0zM12 4.75a7.25 7.25 0 100 14.5 7.25 7.25 0 000-14.5zm-1.338 4.877c-.314.22-.412.452-.412.623 0 .171.098.403.412.623.312.218.783.377 1.338.377.825 0 1.605.233 2.198.648.59.414 1.052 1.057 1.052 1.852 0 .795-.461 1.438-1.052 1.852-.41.286-.907.486-1.448.582v.316a.75.75 0 01-1.5 0v-.316a3.64 3.64 0 01-1.448-.582c-.59-.414-1.052-1.057-1.052-1.852a.75.75 0 011.5 0c0 .171.098.403.412.623.312.218.783.377 1.338.377s1.026-.159 1.338-.377c.314-.22.412-.452.412-.623 0-.171-.098-.403-.412-.623-.312-.218-.783-.377-1.338-.377-.825 0-1.605-.233-2.198-.648-.59-.414-1.052-1.057-1.052-1.852 0-.795.461-1.438 1.052-1.852a3.64 3.64 0 011.448-.582V7.5a.75.75 0 011.5 0v.316c.54.096 1.039.296 1.448.582.59.414 1.052 1.057 1.052 1.852a.75.75 0 01-1.5 0c0-.171-.098-.403-.412-.623-.312-.218-.783-.377-1.338-.377s-1.026.159-1.338.377z" />
</SVG>
);
16 changes: 16 additions & 0 deletions src/blocks/salary-data/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* Internal dependencies
*/
import edit from './edit';
import metadata from './block.json';
import icon from './icon';

const { name } = metadata;

export { metadata, name };

export const settings = {
icon,
example: {},
edit,
};
Loading

0 comments on commit b86b44b

Please sign in to comment.