diff --git a/assets/js/Components/Forms/LabelForm.js b/assets/js/Components/Forms/LabelForm.js
new file mode 100644
index 00000000..00e6c9cf
--- /dev/null
+++ b/assets/js/Components/Forms/LabelForm.js
@@ -0,0 +1,151 @@
+import React, { useEffect, useState } from 'react'
+import { View } from '@instructure/ui-view'
+import { TextInput } from '@instructure/ui-text-input'
+import { Button } from '@instructure/ui-buttons'
+import { IconCheckMarkLine } from '@instructure/ui-icons'
+import { Checkbox } from '@instructure/ui-checkbox'
+import { Spinner } from '@instructure/ui-spinner'
+import * as Html from '../../Services/Html'
+
+export default function LabelForm(props) {
+
+ let html = props.activeIssue.newHtml ? props.activeIssue.newHtml : props.activeIssue.sourceHtml
+
+ if (props.activeIssue.status === '1') {
+ html = props.activeIssue.newHtml
+ }
+
+ let element = Html.toElement(html)
+
+ const [textInputValue, setTextInputValue] = useState(element ? Html.getAttribute(element, "aria-label") : "")
+ // const [deleteLabel, setDeleteLabel] = useState(!element && (props.activeIssue.status === "1"))
+ const [textInputErrors, setTextInputErrors] = useState([])
+
+ let formErrors = []
+
+ useEffect(() => {
+ let html = props.activeIssue.newHtml ? props.activeIssue.newHtml : props.activeIssue.sourceHtml
+ if (props.activeIssue.status === 1) {
+ html = props.activeIssue.newHtml
+ }
+
+ let element = Html.toElement(html)
+ setTextInputValue(element ? Html.getAttribute(element, "aria-label") : "")
+ // setDeleteLabel(!element && props.activeIssue.status === 1)
+
+ formErrors = []
+
+ }, [props.activeIssue])
+
+ useEffect(() => {
+ handleHtmlUpdate()
+ }, [textInputValue])
+
+ const handleHtmlUpdate = () => {
+ let updatedElement = Html.toElement(html)
+
+ updatedElement = Html.setAttribute(updatedElement, "aria-label", textInputValue)
+
+ // if (deleteLabel) {
+ // updatedElement = Html.removeAttribute(updatedElement, "aria-label")
+ // }
+ // else {
+ // updatedElement = Html.setAttribute(updatedElement, "aria-label", textInputValue)
+ // }
+
+ let issue = props.activeIssue
+ issue.newHtml = Html.toString(updatedElement)
+ props.handleActiveIssue(issue)
+
+ }
+
+ const handleButton = () => {
+ formErrors = []
+
+ // if (!deleteLabel) {
+ // checkTextNotEmpty()
+ // }
+
+ checkTextNotEmpty()
+ checkLabelIsUnique()
+
+ if (formErrors.length > 0) {
+ setTextInputErrors(formErrors)
+ }
+ else {
+ props.handleIssueSave(props.activeIssue)
+ }
+ }
+
+ const handleInput = (event) => {
+ setTextInputValue(event.target.value)
+ // handleHtmlUpdate()
+ }
+
+ // const handleCheckbox = () => {
+ // setDeleteLabel(!deleteLabel)
+ // // handleHtmlUpdate()
+ // }
+
+ const checkTextNotEmpty = () => {
+ const text = textInputValue.trim().toLowerCase()
+ if (text === '') {
+ formErrors.push({ text: "Empty label text.", type: "error" })
+ }
+ }
+
+ const checkLabelIsUnique = () => {
+ // in the case of aria_*_label_unique, messageArgs (from metadata) should have the offending label (at the first index)
+ // i guess we could get it from the aria-label itself as well...
+ const issue = props.activeIssue
+ const metadata = issue.metadata ? JSON.parse(issue.metadata) : {}
+ const labelFromMessageArgs = metadata.messageArgs ? metadata.messageArgs[0] : null
+ const text = textInputValue.trim().toLowerCase()
+
+ if (labelFromMessageArgs) {
+ if (text == labelFromMessageArgs) {
+ formErrors.push({ text: "Cannot reuse label text.", type: "error" })
+ }
+ }
+
+ }
+
+ const pending = props.activeIssue && props.activeIssue.pending == "1"
+ const buttonLabel = pending ? "form.processing" : "form.submit"
+
+ return (
+
+
+
+
+ {/*
+
+
+
+ */}
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/assets/js/Services/Ufixit.js b/assets/js/Services/Ufixit.js
index 775bf94d..bb6d91d0 100644
--- a/assets/js/Services/Ufixit.js
+++ b/assets/js/Services/Ufixit.js
@@ -8,6 +8,7 @@ import TableHeaders from '../Components/Forms/TableHeaders'
import Video from '../Components/Forms/Video'
import LinkForm from '../Components/Forms/LinkForm'
import EmphasisForm from '../Components/Forms/EmphasisForm'
+import LabelForm from '../Components/Forms/LabelForm'
const UfixitForms = {
// phpAlly rules
@@ -33,6 +34,8 @@ const UfixitForms = {
// Equal Access Rules
img_alt_misuse: AltText,
+ aria_application_labelled: LabelForm,
+ aria_application_label_unique: LabelForm,
text_contrast_sufficient: ContrastForm,
text_block_heading: HeadingStyleForm,
heading_content_exists: HeadingEmptyForm,
diff --git a/src/Services/AsyncEqualAccessReport.php b/src/Services/AsyncEqualAccessReport.php
index fee28c89..9964a183 100644
--- a/src/Services/AsyncEqualAccessReport.php
+++ b/src/Services/AsyncEqualAccessReport.php
@@ -9,9 +9,12 @@
use Aws\Credentials\Credentials;
use Aws\Signature\SignatureV4;
+use GuzzleHttp\Exception\RequestException;
+use GuzzleHttp\Pool;
use GuzzleHttp\Psr7;
use GuzzleHttp\Promise;
use GuzzleHttp\Client;
+use GuzzleHttp\Psr7\Response;
use Psr\Http\Message\RequestInterface;
use GuzzleHttp\Psr7\Request;
@@ -75,11 +78,9 @@ public function createRequest($payload) {
public function postMultipleArrayAsync(array $contentItems): array {
$promises = [];
- $client = new Client();
$contentItemsReport = [];
- // $this->logToServer("Count contentItems:");
- // $this->logToServer(count($contentItems));
+ $client = new Client();
// Combine every pages into a request
$htmlArray = [];
@@ -91,8 +92,6 @@ public function postMultipleArrayAsync(array $contentItems): array {
// and create and sign a request that we send to the lambda function
$payload = json_encode(["html" => $htmlArray]);
- // $this->logToServer("Creating payload with size {$payloadSize}!");
-
$request = $this->createRequest($payload);
$signedRequest = $this->sign($request);
@@ -102,9 +101,6 @@ public function postMultipleArrayAsync(array $contentItems): array {
$htmlArray = [];
}
- // $this->logToServer("Building up array of size {$payloadSize}:");
- // $this->logToServer($contentItem->getTitle());
-
// Get the HTML then clean up and push a page into an array
$html = $contentItem->getBody();
$document = $this->getDomDocument($html)->saveHTML();
@@ -115,10 +111,6 @@ public function postMultipleArrayAsync(array $contentItems): array {
// Send out any leftover pages we might have
if (count($htmlArray) > 0) {
- // $this->logToServer("Found some leftovers");
- // $pagesPayload = json_encode($htmlArray);
-
- // $this->logToServer(count($htmlArray));
$payload = json_encode(["html" => $htmlArray]);
$request = $this->createRequest($payload);
@@ -127,26 +119,36 @@ public function postMultipleArrayAsync(array $contentItems): array {
$promises[] = $client->sendAsync($signedRequest);
}
-
- // $this->logToServer("waiting for promises...");
+ // $this->logToServer("Number of promises:");
// $this->logToServer(count($promises));
- $results = Promise\Utils::unwrap($promises);
+ $results = Promise\Utils::settle($promises)->wait();
+ // $results = Promise\Utils::unwrap($promises);
+
+ $errors = 0;
foreach ($results as $result) {
- // Every "block" of reports pages should be in a stringified
+ // Every "block" of reports pages should be in a stringified
// JSON, so we need to decode the JSON to be able to iterate through
- // it first.
+ // it first.}
+
+ if (isset($result["value"])) {
+ $response = json_decode($result["value"]->getBody()->getContents(), true);
+ }
+ else if (isset($result["reason"])) {
+ $errors++;
+ }
- $response = json_decode($result->getBody()->getContents(), true);
+ // $this->logToServer($result["value"]->getBody()->getContents());
foreach ($response as $report) {
+ // $this->logToServer(json_encode($report));
$contentItemsReport[] = $report;
}
}
- // $this->logToServer("Number of contentItems we're sending back:");
- // $this->logToServer(count($contentItemsReport));
+ // $this->logToServer("Number of errors:");
+ // $this->logToServer($errors);
return $contentItemsReport;
}