@@ -167,7 +169,7 @@ export default function SettingsPage({
id='lang'
label=''
options={languageOptions}
- settings={settings} />
+ />
@@ -176,9 +178,9 @@ export default function SettingsPage({
-
+
-
{t('welcome.version')} {settings.versionNumber}
+
{t('welcome.version')} {instanceInfo.versionNumber}
{/*
{t('settings.label.release_notes')}
{t('settings.label.documentation')} */}
diff --git a/assets/js/Components/WelcomePage.js b/assets/js/Components/WelcomePage.js
index 162146572..4b9fc6127 100644
--- a/assets/js/Components/WelcomePage.js
+++ b/assets/js/Components/WelcomePage.js
@@ -8,7 +8,8 @@ import './WelcomePage.css'
export default function WelcomePage({
t,
- settings,
+ instanceInfo,
+ preferences,
syncComplete,
setWelcomeClosed
}) {
@@ -21,7 +22,7 @@ export default function WelcomePage({
diff --git a/assets/js/Components/Widgets/BarrierInformation.js b/assets/js/Components/Widgets/BarrierInformation.js
index 77d0d9ec0..742b341db 100644
--- a/assets/js/Components/Widgets/BarrierInformation.js
+++ b/assets/js/Components/Widgets/BarrierInformation.js
@@ -7,12 +7,11 @@ import DisabilityVisualIcon from '../Icons/DisabilityVisualIcon'
import FormClarification from '../Forms/FormClarification'
import { disabilityTypes, disabilitiesFromRule, formNameFromRule } from '../../Services/Ufixit'
import './UfixitWidget.css'
+import { ISSUE_FILTER } from '../../Services/Constants'
export default function BarrierInformation ({
t,
- settings,
-
tempActiveIssue,
handleLearnMoreClick
}) {
@@ -46,7 +45,7 @@ export default function BarrierInformation ({
return
}
- if(tempActiveIssue.contentType === settings.ISSUE_FILTER.FILE_OBJECT) {
+ if(tempActiveIssue.contentType === ISSUE_FILTER.FILE_OBJECT) {
setFormSummary(t('form.file.summary'))
setShowLearnMore(true)
}
diff --git a/assets/js/Components/Widgets/Combobox.js b/assets/js/Components/Widgets/Combobox.js
index 9470f87d3..389be9bc8 100644
--- a/assets/js/Components/Widgets/Combobox.js
+++ b/assets/js/Components/Widgets/Combobox.js
@@ -14,6 +14,7 @@ import ResolvedIcon from '../Icons/ResolvedIcon'
import SortIcon from '../Icons/SortIcon'
import FileTypeIcon from '../Icons/FileTypeIcon'
import './Combobox.css'
+import { FILE_FILTER, ISSUE_FILTER } from '../../Services/Constants'
/* This component is adapted from:
@@ -29,7 +30,6 @@ export default function Combobox({
id = '',
label = '',
options = [],
- settings,
}) {
/* Ideally, the options array contains objects in the form of:
@@ -84,40 +84,40 @@ export default function Combobox({
let size = 'icon-md'
switch(iconString?.toUpperCase()) {
- case settings.ISSUE_FILTER.ISSUE:
+ case ISSUE_FILTER.ISSUE:
return
- case settings.ISSUE_FILTER.POTENTIAL:
- case settings.ISSUE_FILTER.UNREVIEWED:
+ case ISSUE_FILTER.POTENTIAL:
+ case ISSUE_FILTER.UNREVIEWED:
return
- case settings.ISSUE_FILTER.ANNOUNCEMENT:
+ case ISSUE_FILTER.ANNOUNCEMENT:
return
- case settings.ISSUE_FILTER.ASSIGNMENT:
+ case ISSUE_FILTER.ASSIGNMENT:
return
- case settings.ISSUE_FILTER.DISCUSSION_FORUM:
+ case ISSUE_FILTER.DISCUSSION_FORUM:
return
- case settings.ISSUE_FILTER.DISCUSSION_TOPIC:
+ case ISSUE_FILTER.DISCUSSION_TOPIC:
return
- case settings.ISSUE_FILTER.FILE:
+ case ISSUE_FILTER.FILE:
return
- case settings.ISSUE_FILTER.PAGE:
+ case ISSUE_FILTER.PAGE:
return
- case settings.ISSUE_FILTER.QUIZ:
+ case ISSUE_FILTER.QUIZ:
return
- case settings.ISSUE_FILTER.SYLLABUS:
+ case ISSUE_FILTER.SYLLABUS:
return
- case settings.ISSUE_FILTER.FIXED:
- case settings.ISSUE_FILTER.FIXEDANDRESOLVED:
+ case ISSUE_FILTER.FIXED:
+ case ISSUE_FILTER.FIXEDANDRESOLVED:
return
- case settings.ISSUE_FILTER.RESOLVED:
- case settings.ISSUE_FILTER.REVIEWED:
- case settings.FILE_FILTER.REVIEWED:
+ case ISSUE_FILTER.RESOLVED:
+ case ISSUE_FILTER.REVIEWED:
+ case FILE_FILTER.REVIEWED:
return
- case settings.FILE_FILTER.FILE_PDF:
- case settings.FILE_FILTER.FILE_WORD:
- case settings.FILE_FILTER.FILE_POWERPOINT:
- case settings.FILE_FILTER.FILE_EXCEL:
- case settings.FILE_FILTER.FILE_AUDIO:
- case settings.FILE_FILTER.FILE_VIDEO:
+ case FILE_FILTER.FILE_PDF:
+ case FILE_FILTER.FILE_WORD:
+ case FILE_FILTER.FILE_POWERPOINT:
+ case FILE_FILTER.FILE_EXCEL:
+ case FILE_FILTER.FILE_AUDIO:
+ case FILE_FILTER.FILE_VIDEO:
return
default:
return ''
diff --git a/assets/js/Components/Widgets/FileFixitWidget.js b/assets/js/Components/Widgets/FileFixitWidget.js
index 0e4685e6f..31f55cb39 100644
--- a/assets/js/Components/Widgets/FileFixitWidget.js
+++ b/assets/js/Components/Widgets/FileFixitWidget.js
@@ -9,7 +9,6 @@ import SeverityIssueIconFilled from '../Icons/SeverityIssueIconFilled'
export default function FileFixitWidget({
t,
- settings,
sessionFiles,
tempActiveIssue,
uploadedFile,
@@ -36,7 +35,6 @@ export default function FileFixitWidget({
@@ -50,7 +48,6 @@ export default function FileFixitWidget({
{
@@ -162,7 +161,6 @@ export default function FixIssuesFilters({
id={detailedFilters[index].value}
label={detailedFilters[index].label}
options={detailedFilters[index].options}
- settings={settings}
/>
)
diff --git a/assets/js/Components/Widgets/FixIssuesList.js b/assets/js/Components/Widgets/FixIssuesList.js
index f081788ee..4bf3f02e6 100644
--- a/assets/js/Components/Widgets/FixIssuesList.js
+++ b/assets/js/Components/Widgets/FixIssuesList.js
@@ -5,11 +5,10 @@ import StatusPill from './StatusPill'
import SortIcon from '../Icons/SortIcon'
import './FixIssuesList.css'
+import { ISSUE_FILTER } from '../../Services/Constants'
export default function FixIssuesList({
t,
- settings,
-
groupedList,
setActiveIssue
}) {
@@ -33,13 +32,13 @@ export default function FixIssuesList({
"Known Barrier, Page, 'Welcome to the course', found in: 'Introduction Module' */
const getIssueLabel = (issue) => {
let label = ''
- if(issue.status === settings.ISSUE_FILTER.ACTIVE) {
+ if(issue.status === ISSUE_FILTER.ACTIVE) {
label += t(`filter.label.severity.${issue.severity.toLowerCase()}_single`) + ', '
}
- else if (issue.status === settings.ISSUE_FILTER.FIXED || issue.status == settings.ISSUE_FILTER.FIXEDANDRESOLVED) {
+ else if (issue.status === ISSUE_FILTER.FIXED || issue.status == ISSUE_FILTER.FIXEDANDRESOLVED) {
label += t('filter.label.resolution.fixed_single') + ', '
}
- else if (issue.status === settings.ISSUE_FILTER.RESOLVED) {
+ else if (issue.status === ISSUE_FILTER.RESOLVED) {
label += t('filter.label.resolution.resolved_single') + ', '
}
@@ -129,7 +128,6 @@ export default function FixIssuesList({
{
diff --git a/assets/js/Components/Widgets/ReviewFilesFilters.js b/assets/js/Components/Widgets/ReviewFilesFilters.js
index 0ac09123b..ea12dc417 100644
--- a/assets/js/Components/Widgets/ReviewFilesFilters.js
+++ b/assets/js/Components/Widgets/ReviewFilesFilters.js
@@ -2,13 +2,14 @@ import React, { useState, useEffect } from 'react'
import SearchIcon from '../Icons/SearchIcon'
import Combobox from './Combobox'
import ToggleSwitch from './ToggleSwitch'
+import { FILE_FILTER as FILTER} from '../../Services/Constants'
import './FixIssuesFilters.css'
+import { DEFAULT_USER_SETTINGS } from '../../Services/Settings'
export default function ReviewFilesFilters({
t,
- settings,
-
+ preferences,
activeFilters,
handleSearchTerm,
searchTerm,
@@ -16,8 +17,6 @@ export default function ReviewFilesFilters({
updateActiveFilters
}) {
- const FILTER = settings.FILE_FILTER
-
const filterLabels = {
[FILTER.TYPE.UTILIZATION]: t('filter.label.utilization'),
[FILTER.TYPE.FILE_TYPE]: t('filter.label.file_type'),
@@ -43,7 +42,7 @@ export default function ReviewFilesFilters({
const [usedFilters, setUsedFilters] = useState(null)
const [detailedFilters, setDetailedFilters] = useState(null)
// For new users, the 'show_filters' attribute may not be set, so we need to check if it exists before using it
- const [showFilters, setShowFilters] = useState(settings?.user?.roles && ('show_filters' in settings.user.roles) ? settings.user.roles.show_filters : settings.DEFAULT_USER_SETTINGS.SHOW_FILTERS)
+ const [showFilters, setShowFilters] = useState(preferences.showFilters ?? DEFAULT_USER_SETTINGS.SHOW_FILTERS)
// When the page loads, only show the "Modules" filter is there are modules to filter by...
useEffect(() => {
@@ -156,7 +155,6 @@ export default function ReviewFilesFilters({
id={detailedFilters[index].value}
label={detailedFilters[index].label}
options={detailedFilters[index].options}
- settings={settings}
/>
)
diff --git a/assets/js/Components/Widgets/StatusPill.js b/assets/js/Components/Widgets/StatusPill.js
index 1908c3179..e21887df9 100644
--- a/assets/js/Components/Widgets/StatusPill.js
+++ b/assets/js/Components/Widgets/StatusPill.js
@@ -4,36 +4,36 @@ import SeverityIcon from '../Icons/SeverityIcon'
import SeverityPotentialIcon from '../Icons/SeverityPotentialIcon'
import ResolvedIcon from '../Icons/ResolvedIcon'
import FixedIcon from '../Icons/FixedIcon'
+import { FILE_FILTER, ISSUE_FILTER } from '../../Services/Constants'
export default function StatusPill({
t,
- settings,
issue,
}) {
return (
<>
- { issue.status === settings.ISSUE_FILTER.ACTIVE ? (
+ { issue.status === ISSUE_FILTER.ACTIVE ? (
{t(`filter.label.severity.${issue.severity.toLowerCase()}_single`)}
- ) : (issue.status === settings.ISSUE_FILTER.FIXED || issue.status == settings.ISSUE_FILTER.FIXEDANDRESOLVED) ? (
+ ) : (issue.status === ISSUE_FILTER.FIXED || issue.status == ISSUE_FILTER.FIXEDANDRESOLVED) ? (
{t('filter.label.resolution.fixed_single')}
- ) : (issue.status === settings.ISSUE_FILTER.RESOLVED) ? (
+ ) : (issue.status === ISSUE_FILTER.RESOLVED) ? (
{t('filter.label.resolution.resolved_single')}
- ) : (issue.status === settings.FILE_FILTER.UNREVIEWED) ? (
+ ) : (issue.status === FILE_FILTER.UNREVIEWED) ? (
{t('fix.label.status.unreviewed')}
- ) : (issue.status === settings.FILE_FILTER.REVIEWED) ? (
+ ) : (issue.status === FILE_FILTER.REVIEWED) ? (
{t('fix.label.status.reviewed')}
diff --git a/assets/js/Components/Widgets/UfixitWidget.js b/assets/js/Components/Widgets/UfixitWidget.js
index dfc7445a4..613f99012 100644
--- a/assets/js/Components/Widgets/UfixitWidget.js
+++ b/assets/js/Components/Widgets/UfixitWidget.js
@@ -4,12 +4,13 @@ import FileForm from '../Forms/FileForm'
import StatusPill from './StatusPill'
import { formFromIssue } from '../../Services/Ufixit'
import './UfixitWidget.css'
+import { ISSUE_FILTER, UFIXIT_OPTIONS } from '../../Services/Constants'
export default function UfixitWidget({
t,
- settings,
+ formOptions,
activeContentItem,
handleActiveContentItem,
@@ -43,10 +44,10 @@ export default function UfixitWidget({
}
if(tempActiveIssue.isModified === undefined) {
- setMarkAsReviewed(tempActiveIssue.status === settings.ISSUE_FILTER.RESOLVED || tempActiveIssue.status === settings.ISSUE_FILTER.FIXEDANDRESOLVED)
+ setMarkAsReviewed(tempActiveIssue.status === ISSUE_FILTER.RESOLVED || tempActiveIssue.status === ISSUE_FILTER.FIXEDANDRESOLVED)
}
- if(tempActiveIssue.contentType === settings.ISSUE_FILTER.FILE_OBJECT) {
+ if(tempActiveIssue.contentType === ISSUE_FILTER.FILE_OBJECT) {
setUfixitForm(() => { return FileForm })
}
else {
@@ -86,7 +87,7 @@ export default function UfixitWidget({
const handleOptionChange = (option) => {
setActiveOption(option)
- if (option === settings.UFIXIT_OPTIONS.MARK_AS_REVIEWED) {
+ if (option === UFIXIT_OPTIONS.MARK_AS_REVIEWED) {
setMarkAsReviewed(true)
}
else {
@@ -106,7 +107,6 @@ export default function UfixitWidget({
@@ -116,14 +116,13 @@ export default function UfixitWidget({
{
return sectionReference
}
-export function analyzeReport(report, ISSUE_STATE) {
+export function analyzeReport(report) {
let tempReport = {
contentFixed: report.contentFixed || 0,
contentResolved: report.contentResolved || 0,
diff --git a/assets/js/Services/Settings.js b/assets/js/Services/Settings.js
index c0a435b0f..64d29dc9c 100644
--- a/assets/js/Services/Settings.js
+++ b/assets/js/Services/Settings.js
@@ -1,107 +1,3 @@
-export const ISSUE_STATE = {
- UNCHANGED: 0,
- SAVING: 1,
- RESOLVING: 2,
- SAVED: 3,
- RESOLVED: 4,
- ERROR: 5,
-}
-
-export const WIDGET_STATE = {
- LOADING: 0,
- FIXIT: 1,
- LEARN: 2,
- LIST: 3,
- NO_RESULTS: 4,
-}
-
-// Define the kinds of issue filters that will be available to the user
-export const ISSUE_FILTER = {
- TYPE: {
- SEVERITY: 'SEVERITY',
- CONTENT_TYPE: 'CONTENT_TYPE',
- RESOLUTION: 'RESOLUTION',
- MODULE: 'MODULE',
- PUBLISHED: 'PUBLISHED',
- },
- ALL: 'ALL',
- ISSUE: 'ISSUE',
- POTENTIAL: 'POTENTIAL',
- SUGGESTION: 'SUGGESTION',
- PAGE: 'PAGE',
- ASSIGNMENT: 'ASSIGNMENT',
- ANNOUNCEMENT: 'ANNOUNCEMENT',
- DISCUSSION_TOPIC: 'DISCUSSION_TOPIC',
- DISCUSSION_FORUM: 'DISCUSSION_FORUM',
- FILE: 'FILE',
- QUIZ: 'QUIZ',
- SYLLABUS: 'SYLLABUS',
- MODULE: 'MODULE',
- FILE_OBJECT: 'FILE_OBJECT',
- ACTIVE: 'ACTIVE',
- FIXED: 'FIXED',
- RESOLVED: 'RESOLVED',
- FIXEDANDRESOLVED: 'FIXEDANDRESOLVED', // Doesn't appear in any dropdowns, but is used in the code
- PUBLISHED: 'PUBLISHED',
- UNPUBLISHED: 'UNPUBLISHED',
-}
-
-export const FILE_FILTER = {
- TYPE: {
- UTILIZATION: 'UTILIZATION',
- PUBLISHED: 'PUBLISHED',
- FILE_TYPE: 'FILE_TYPE',
- RESOLUTION: 'RESOLUTION',
- MODULE: 'MODULE',
- },
- ALL: 'ALL',
- USED: 'USED',
- UNUSED: 'UNUSED',
- PUBLISHED: 'PUBLISHED',
- UNPUBLISHED: 'UNPUBLISHED',
- FILE_PDF: 'PDF',
- FILE_WORD: 'WORD',
- FILE_POWERPOINT: 'POWERPOINT',
- FILE_EXCEL: 'EXCEL',
- FILE_VIDEO: 'VIDEO',
- FILE_AUDIO: 'AUDIO',
- FILE_UNKNOWN: 'UNKNOWN',
- ACTIVE: 'ACTIVE',
- UNREVIEWED: 'UNREVIEWED',
- REVIEWED: 'REVIEWED',
- REPLACED: 'REPLACED',
- FILE_OBJECT: 'FILE_OBJECT',
-}
-
-export const FILE_TYPES = [
- 'pdf',
- 'doc',
- 'ppt',
- 'xls',
- 'audio',
- 'video',
-]
-
-export const FILE_TYPE_MAP = {
- 'pdf': FILE_FILTER.FILE_PDF,
- 'doc': FILE_FILTER.FILE_WORD,
- 'ppt': FILE_FILTER.FILE_POWERPOINT,
- 'xls': FILE_FILTER.FILE_EXCEL,
- 'audio': FILE_FILTER.FILE_AUDIO,
- 'video': FILE_FILTER.FILE_VIDEO,
-}
-
-export const UFIXIT_OPTIONS = {
- ADD_EMPHASIS: 'add-emphasis',
- ADD_TEXT: 'add-text',
- DELETE_ATTRIBUTE: 'delete-attribute',
- DELETE_ELEMENT: 'delete-element',
- MARK_AS_REVIEWED: 'mark-as-reviewed',
- MARK_DECORATIVE: 'mark-decorative',
- SELECT_ATTRIBUTE_VALUE: 'select-attribute-value',
- SELECT_TAG: 'select-tag'
-}
-
export const DEFAULT_USER_SETTINGS = {
ALERT_TIMEOUT: '5000',
FONT_SIZE: 'font-medium',
@@ -112,12 +8,12 @@ export const DEFAULT_USER_SETTINGS = {
LANGUAGE: 'en',
}
-export function findEditURLWithIssue(issue, settings) {
- if (!issue || !settings || !settings.institution) {
+export function findEditURLWithIssue(issue, instanceInfo) {
+ if (!issue || !instanceInfo || !instanceInfo.institution) {
return ''
}
- let lms = settings.institution.lmsId
+ let lms = instanceInfo.institution.lmsId
if (lms === 'canvas') {
return `${issue.contentUrl}/edit`
} else {
diff --git a/src/Controller/AdminController.php b/src/Controller/AdminController.php
index 3133a828c..87eab1e14 100644
--- a/src/Controller/AdminController.php
+++ b/src/Controller/AdminController.php
@@ -13,6 +13,7 @@
use App\Services\LmsUserService;
use App\Services\SessionService;
use App\Services\UtilityService;
+use App\Services\InitialStateService;
use App\Repository\CourseUserRepository;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
@@ -89,7 +90,8 @@ public function settingsApi(
UtilityService $util,
SessionService $sessionService,
LmsApiService $lmsApi,
- CourseRepository $courseRepo): JsonResponse
+ CourseRepository $courseRepo,
+ InitialStateService $initialStateService): JsonResponse
{
$this->util = $util;
$this->session = $sessionService->getSession();
@@ -101,9 +103,23 @@ public function settingsApi(
return new JsonResponse(['error' => 'Unauthenticated'], 401);
}
+ $preferences = $initialStateService->getPreferences($user);
+
+ $lms = $lmsApi->getLms();
+
+ if (!($accountId = $this->session->get('lms_account_id'))) {
+ $this->util->exitWithMessage('Account ID not found.');
+ }
+
+ $accounts = $lms->getAccountData($user, $accountId);
+
return new JsonResponse([
- 'settings' => $this->getSettings(),
- 'messages' => $this->util->getUnreadMessages(true),
+ 'messages' => $util->getUnreadMessages(true),
+ 'preferences' => $preferences,
+ 'instanceInfo' => $initialStateService->getInstanceInfo($user),
+ 'labels' => $initialStateService->getLabels($preferences),
+ 'accounts' => $accounts,
+ 'termInfo' => $this->getTermInfo($accounts),
]);
}
@@ -657,26 +673,11 @@ public function getUpdatedAccounts(
/** PROTECTED FUNCTIONS **/
- protected function getSettings(): array
+ protected function getTermInfo($accounts): array
{
$lms = $this->lmsApi->getLms();
-
- /** @var User $user */
$user = $this->getUser();
- /** @var \App\Entity\Institution $institution */
- $institution = $user->getInstitution();
- $metadata = $institution->getMetadata();
- /** $lang should be two letters, and match an available JSON file in the /translations folder. */
- $lang = ($_ENV['DEFAULT_LANG'] ? $_ENV['DEFAULT_LANG'] : 'en');
- $lang = (!empty($metadata['lang'])) ? $metadata['lang'] : $lang;
- $lang = (array_key_exists("lang", $user->getRoles()) ? $user->getRoles()["lang"] : $lang);
- $excludedRuleIds = (!empty($metadata['excludedRuleIds'])) ? $metadata['excludedRuleIds'] : $_ENV['PHPALLY_EXCLUDED_RULES'];
-
- if (!($accountId = $this->session->get('lms_account_id'))) {
- $this->util->exitWithMessage('Account ID not found.');
- }
-
- $accounts = $lms->getAccountData($user, $accountId);
+
$terms = $lms->getAccountTerms($user);
$terms = $this->filterTermsByAccount($terms, $accounts);
$defaultTerm = $this->getDefaultTerm($terms);
@@ -688,17 +689,8 @@ protected function getSettings(): array
}
return [
- 'apiUrl' => !empty($_ENV['BASE_URL']) ? $_ENV['BASE_URL'] : false,
- 'user' => $user,
- 'institution' => $institution,
- 'roles' => $this->session->get('roles'),
- 'language' => $lang,
- 'labels' => $this->util->getTranslation($lang),
- 'excludedRuleIds' => $excludedRuleIds,
- 'accounts' => $accounts,
'terms' => $simpleTerms,
'defaultTerm' => $defaultTerm,
- 'suggestionRuleIds' => !empty($_ENV['PHPALLY_SUGGESTION_RULES']) ? $_ENV['PHPALLY_SUGGESTION_RULES'] : '',
];
}
@@ -726,6 +718,7 @@ protected function getCourseData(Course $course, User $user)
'canScan' => true,
];
}
+
protected function filterTermsByAccount($terms, $accounts)
{
diff --git a/src/Controller/DashboardController.php b/src/Controller/DashboardController.php
index 72faf4b6c..473d0cc20 100644
--- a/src/Controller/DashboardController.php
+++ b/src/Controller/DashboardController.php
@@ -9,6 +9,7 @@
use App\Services\LmsUserService;
use App\Services\SessionService;
use App\Services\UtilityService;
+use App\Services\InitialStateService;
use Doctrine\Persistence\ManagerRegistry;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
@@ -82,7 +83,8 @@ public function index(
public function settingsApi(
UtilityService $util,
SessionService $sessionService,
- LmsApiService $lmsApi): JsonResponse
+ LmsApiService $lmsApi,
+ InitialStateService $initialStateService,): JsonResponse
{
$this->util = $util;
$this->session = $sessionService->getSession();
@@ -105,45 +107,21 @@ public function settingsApi(
$course = $this->createCourse($user->getInstitution(), $lmsCourseId);
}
+ $preferences = $initialStateService->getPreferences($user);
+
return new JsonResponse([
- 'settings' => $this->getSettings($course),
- 'messages' => $this->util->getUnreadMessages(true),
+ 'messages' => $this->util->getUnreadMessages(true),
+ 'preferences' => $preferences,
+ 'labels' => $initialStateService->getLabels($preferences),
+ 'instanceInfo' => $initialStateService->getInstanceInfo($user, $course),
+ 'formOptions' => [
+ 'backgroundColor' => !empty($_ENV['BACKGROUND_COLOR']) ? $_ENV['BACKGROUND_COLOR'] : '#ffffff',
+ 'textColor' => !empty($_ENV['TEXT_COLOR']) ? $_ENV['TEXT_COLOR'] : '#000000',
+ ],
]);
}
- protected function getSettings(Course $course): array
- {
- /** @var User $user */
- $user = $this->getUser();
- /** @var \App\Entity\Institution $institution */
- $institution = $user->getInstitution();
-
- $metadata = $institution->getMetadata();
-
- /** $lang should be two letters, and match an available JSON file in the /translations folder. */
- $lang = ($_ENV['DEFAULT_LANG'] ? $_ENV['DEFAULT_LANG'] : 'en');
- $lang = (!empty($metadata['lang'])) ? $metadata['lang'] : $lang;
- $lang = (array_key_exists("lang", $user->getRoles()) ? $user->getRoles()["lang"] : $lang);
- $excludedRuleIds = (!empty($metadata['excludedRuleIds'])) ? $metadata['excludedRuleIds'] : $_ENV['PHPALLY_EXCLUDED_RULES'];
-
- $lms = $this->lmsApi->getLms();
-
- return [
- 'apiUrl' => !empty($_ENV['BASE_URL']) ? $_ENV['BASE_URL'] : false,
- 'user' => $user,
- 'course' => $course,
- 'institution' => $institution,
- 'roles' => $this->session->get('roles'),
- 'language' => $lang,
- 'labels' => (array) $this->util->getTranslation($lang),
- 'excludedRuleIds' => $excludedRuleIds,
- 'contentTypes' => $lms->getContentTypes(),
- 'backgroundColor' => !empty($_ENV['BACKGROUND_COLOR']) ? $_ENV['BACKGROUND_COLOR'] : '#ffffff',
- 'textColor' => !empty($_ENV['TEXT_COLOR']) ? $_ENV['TEXT_COLOR'] : '#000000',
- 'versionNumber' => !empty($_ENV['VERSION_NUMBER']) ? $_ENV['VERSION_NUMBER'] : '',
- ];
- }
-
+
protected function createCourse(Institution $institution, $lmsCourseId)
{
$course = new Course();
diff --git a/src/Controller/UserController.php b/src/Controller/UserController.php
index 780a653e9..61cc15653 100644
--- a/src/Controller/UserController.php
+++ b/src/Controller/UserController.php
@@ -25,7 +25,7 @@ public function __construct(ManagerRegistry $doctrine)
$this->doctrine = $doctrine;
}
- #[Route('/api/users/{user}', name: 'user_put', methods: ['PUT'])]
+ #[Route('/api/users/{user}/preferences', name: 'user_preferences_patch', methods: ['PATCH'])]
public function update(SessionService $sessionService, User $user, Request $request, UtilityService $util): JsonResponse
{
$apiResponse = new ApiResponse();
@@ -42,32 +42,48 @@ public function update(SessionService $sessionService, User $user, Request $requ
throw new \Exception("msg.no_permissions");
}
- $userVals = \json_decode($request->getContent(), true);
+ $newPreferences = \json_decode($request->getContent(), true);
$oldRoles = $user->getRoles();
$oldLang = $oldRoles['lang'] ?? 'en';
- $newRoles = $userVals['roles'] ?? [];
- $newLang = $newRoles['lang'] ?? 'en';
- $changeLang = ($oldLang !== $newLang);
+ // Preference IDs on the client differ from DB column names, so we must translate
+ $roleMap = [
+ 'textSpacing' => 'text_spacing',
+ 'fontSize' => 'font_size',
+ 'fontFamily' => 'font_family',
+ 'darkMode' => 'dark_mode',
+ 'alertTimeout' => 'alert_timeout',
+ 'dailyGoal' => 'daily_goal',
+ 'showFilters' => 'show_filters',
+ 'viewOnlyPublished' => 'view_only_published',
+ 'lang' => 'lang'
+ ];
- $user->setRoles($newRoles);
- if (empty($userVals['hasApiKey'])) {
- $user->setApiKey('');
- $user->setRefreshToken('');
+ $newRoles = $oldRoles;
+
+ foreach($newPreferences as $roleKey => $roleValue)
+ {
+ if (!isset($roleMap[$roleKey])) continue;
+ $newKey = $roleMap[$roleKey];
+ $newRoles[$newKey] = $roleValue;
}
+
+
+ $changeLang = (!empty($newRoles['lang']) && $oldLang !== $newRoles['lang']);
+
+ $user->setRoles($newRoles);
$responseObject = [
'user' => $user,
- 'language' => $newLang,
- 'labels' => [],
+ 'labels' => NULL,
];
if ($changeLang) {
$this->util = $util;
- $labels = $this->util->getTranslation($newLang);
+ $labels = $this->util->getTranslation($newRoles['lang']);
$responseObject['labels'] = $labels;
}
diff --git a/src/Services/InitialStateService.php b/src/Services/InitialStateService.php
new file mode 100644
index 000000000..3ed8fa8cd
--- /dev/null
+++ b/src/Services/InitialStateService.php
@@ -0,0 +1,77 @@
+util = $util;
+ }
+
+ public function getPreferences(User $user): array
+ {
+ $roles = $user->getRoles();
+ $institution = $user->getInstitution();
+ $metadata = $institution->getMetadata();
+
+ $lang = $_ENV['DEFAULT_LANG'] ?? 'en';
+ $lang = !empty($metadata['lang']) ? $metadata['lang'] : $lang;
+ $lang = array_key_exists('lang', $roles) ? $roles['lang'] : $lang;
+
+ return [
+ 'textSpacing' => $roles['text_spacing'] ?? null,
+ 'fontSize' => $roles['font_size'] ?? null,
+ 'fontFamily' => $roles['font_family'] ?? null,
+ 'darkMode' => $roles['dark_mode'] ?? null,
+ 'alertTimeout' => $roles['alert_timeout'] ?? null,
+ 'dailyGoal' => $roles['daily_goal'] ?? null,
+ 'showFilters' => $roles['show_filters'] ?? null,
+ 'viewOnlyPublished' => $roles['view_only_published'] ?? null,
+ 'lang' => $lang,
+ ];
+ }
+
+ public function getInstanceInfo(User $user, $course = null): array
+ {
+ $institution = $user->getInstitution();
+ $metadata = $institution->getMetadata();
+
+ return [
+ 'apiUrl' => !empty($_ENV['BASE_URL']) ? $_ENV['BASE_URL'] : false,
+ 'course' => $course,
+ 'institution' => $institution,
+ 'versionNumber' => $_ENV['VERSION_NUMBER'] ?? '',
+ 'excludedRuleIds' => !empty($metadata['excludedRuleIds'])
+ ? $metadata['excludedRuleIds']
+ : $_ENV['PHPALLY_EXCLUDED_RULES'],
+ 'user' => [
+ 'id' => $user->getId(),
+ 'username' => $user->getUserIdentifier(),
+ 'name' => $user->getName(),
+ ],
+ ];
+ }
+
+ public function getLabels(array $preferences): array
+ {
+ return (array) $this->util->getTranslation($preferences['lang']);
+ }
+
+ public function getFormOptions(): array
+ {
+ return [
+ 'backgroundColor' => !empty($_ENV['BACKGROUND_COLOR']) ? $_ENV['BACKGROUND_COLOR'] : '#ffffff',
+ 'textColor' => !empty($_ENV['TEXT_COLOR']) ? $_ENV['TEXT_COLOR'] : '#000000',
+ ];
+ }
+}
\ No newline at end of file