Skip to content

Commit

Permalink
Merge pull request #3733 from Tangerine-Community/release/v3.31.1
Browse files Browse the repository at this point in the history
Release v3.31.1
  • Loading branch information
esurface authored Dec 9, 2024
2 parents 7e2cc5d + fe05493 commit a5422da
Show file tree
Hide file tree
Showing 30 changed files with 360 additions and 116 deletions.
33 changes: 33 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,38 @@
# What's new

## v3.31.1

__General Updates__

- Allow mysql outputs of TANGY-TIMED and TANGY-UNTIMED-GRID data

__Administration__

- The `reporting-cache-clear` script will honor the environmnt variable `T_ONLY_PROCESS_THESE_GROUPS` to limit the groups processed
* Set `T_ONLY_PROCESS_THESE_GROUPS` to a comma-separated list of group names to limit the groups cleared and then processed by the script

__Fixes__
- Fixes for editing of Form Responses in the server web UI
* Edits of Attendence, Behavior, and Scoring are currently prohibited in the server web UI
* Verified and Archived Form Responses must be Unverified and Unarchived before editing is available
- Teacher Dashboard Scoring: Fix issues with custom scoring
- Fix output of Case Participants to mysql
- Fix online survey release

__Libs and Dependencies__
- Bump version of `tangy-form` to v4.54.4
* Fix check for 'readOnly' input metadata
* Fix undefined access of input without tagName
* Fix missing function parens

__Server upgrade instructions__

See the [Server Upgrade Insturctions](https://docs.tangerinecentral.org/system-administrator/upgrade-instructions).

*Special Instructions for this release:* N/A



## v3.31.0

__New Features__
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ RUN cd /tangerine/online-survey-app && \
./node_modules/.bin/ng build --base-href "./"

# build client.
add client /tangerine/client
ADD client /tangerine/client
RUN cd /tangerine/client && \
./node_modules/.bin/ng build --base-href "./"

Expand Down
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,14 +144,15 @@ We use a tool called `tangerine-preview` to do local content development. Note t
### Develop for Editor and Server
Docker and git is required for local development. For Mac, download and install [Docker for Desktop](https://www.docker.com/products/docker-desktop). For Windows you will also use Docker for Desktop, but we suggest using the instructions [here](https://docs.docker.com/docker-for-windows/wsl/) which will also point you towards documentation for installing WSL2 on Windows.

1. Run the following commands to clone and set up Tangerine for development:
```bash
git clone git@github.com:tangerine-community/tangerine
cd tangerine
cp config.defaults.sh config.sh
./develop.sh
```

Now open <http://localhost/> in your web browser. To debug the node.js server, install [NiM](https://chrome.google.com/webstore/detail/nodejs-v8-inspector-manag/gnhhdgbaldcilmgcpfddgdbkhjohddkj), open it through your devtools and connect to port 9229.
2. Edit config.sh making the necessary changes to the variables.
3. Then run `./develop.sh` to start up Tangerine. The initial start up process my take more than 20 minutes.
4. Now open <http://localhost/> in your web browser. To debug the node.js server, install [NiM](https://chrome.google.com/webstore/detail/nodejs-v8-inspector-manag/gnhhdgbaldcilmgcpfddgdbkhjohddkj), open it through your devtools and connect to port 9229.

__Optional__: If you want to test deploying APKs and PWAs, you'll need to make your sandbox accessible using an https URL. A reverse proxy will forward https requests to your dev instance running on port 80. Tangerine Developers have had good luck using [tunnelto](https://tunnelto.dev/) and [ngrok](https://ngrok.com/) to create an https tunnel to your local server. Please note that using those methods expose your dev environment to the Internet. An alternative is to create your own reverse proxy - see the [Reverse Proxy for Developers](./docs/developer/reverse-proxy-for-developers.md) doc for more information.

Expand Down
2 changes: 1 addition & 1 deletion client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@
"rxjs-compat": "^6.5.5",
"sanitize-filename-ts": "^1.0.2",
"spark-md5": "^3.0.2",
"tangy-form": "^4.43.2",
"tangy-form": "^4.45.4",
"translation-web-component": "1.1.1",
"tslib": "^1.10.0",
"underscore": "^1.9.1",
Expand Down
30 changes: 25 additions & 5 deletions client/src/app/class/_services/dashboard.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -430,7 +430,7 @@ export class DashboardService {
totalIncorrect: totalIncorrect,
maxValueAnswer: maxValueAnswer,
totalCorrect: totalCorrect,
scorePercentageCorrect: scorePercentageCorrect,
scorePercentageCorrect: customScore ? customScore : scorePercentageCorrect,
duration: duration,
customScore: customScore
};
Expand Down Expand Up @@ -690,9 +690,7 @@ export class DashboardService {
}

/**
* Special parsing for enabled curriculums.
* By default returns the curriculum name.
* Set provideCurriculumObject if you want a special curriculum Object, which is useful for menu labels.
* Parse a variable value from a response.
* */
public getValue = (variableName, response) => {
if (response) {
Expand All @@ -706,6 +704,27 @@ export class DashboardService {
}
};

/**
* Parse the variable options.
*/
public getOptions = (variableName, response) => {
let options = [];
if (response) {
const variablesByName = response.items.reduce((variablesByName, item) => {
for (const input of item.inputs) {
variablesByName[input.name] = input.value;
}
return variablesByName;
}, {});
if (Array.isArray(variablesByName[variableName])) {
options = variablesByName[variableName].map((option) => option.name, '');
} else if (variablesByName[variableName]) {
options.push(variablesByName[variableName]);
}
}
return options;
}

/**
* Special parsing for enabled curriculums.
* By default returns a special curriculum Object, which is useful for menu labels.
Expand Down Expand Up @@ -1500,12 +1519,13 @@ export class DashboardService {
return currentClass;
}

buildAttendanceReport(id: string, timestamp: number, currentClassId, grade, schoolName, schoolYear, reportDate: string, type: string, attendanceList) {
buildAttendanceReport(id: string, timestamp: number, currentClassId, grade, schoolName, schoolYear, reportDate: string, type: string, attendanceList, period='') {
return {
_id: id,
timestamp: timestamp,
classId: currentClassId,
grade: grade,
period: period,
schoolName: schoolName,
schoolYear: schoolYear,
reportDate: reportDate,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
<mat-card>
<div class="selectedClassLabel">{{'Attendance'|translate}}<br/>{{getClassTitle(selectedClass)}} <ng-container *ngIf="!ignoreCurriculumsForTracking">: {{curriculum?.label}} </ng-container>: {{reportLocaltime}}</div>
<div class="selectedClassLabel">{{'Attendance'|translate}}<br/>{{getClassTitle(selectedClass)}}
<ng-container *ngIf="!ignoreCurriculumsForTracking">: {{curriculum?.label}} </ng-container>: {{reportLocaltime}}
</div>
<div id="period-dropdown" class="selectedClassLabel">
<ng-container *ngIf="periodsLength > 0">
<mat-form-field>
<mat-label>{{'Period'|translate}}</mat-label>
<mat-select [(value)]="selectedPeriod" (selectionChange)="onPeriodChange($event)">
<mat-option *ngFor="let period of periods" [value]="period">{{period}}</mat-option>
</mat-select>
</mat-form-field>
</ng-container>
</div>
<div class="tableHintLabel">
<mat-label>{{'Tap on the green checkmark to mark a student as absent'|translate}}</mat-label>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export class AttendanceCheckComponent implements OnInit {
timestamp: number,
classId: string,
grade: string,
period: string,
schoolName: string
schoolYear: string,
reportDate:string,
Expand All @@ -36,6 +37,9 @@ export class AttendanceCheckComponent implements OnInit {
complete: boolean,
type: string
}
periods: string[]
periodsLength: number = 0
selectedPeriod: string = ''
selectedClass: any
behaviorForms: Promise<FormMetadata[]>;
curriculum:any
Expand Down Expand Up @@ -73,6 +77,8 @@ export class AttendanceCheckComponent implements OnInit {
const currentClass = this.dashboardService.getSelectedClass(enabledClasses, classIndex)
this.selectedClass = currentClass;
this.ignoreCurriculumsForTracking = this.dashboardService.getValue('ignoreCurriculumsForTracking', currentClass)
this.periods = this.dashboardService.getOptions('period', currentClass);
this.periodsLength = this.periods.length

const currArray = await this.dashboardService.populateCurrentCurriculums(currentClass);
const curriculumId = await this.variableService.get('class-curriculumId');
Expand Down Expand Up @@ -129,15 +135,25 @@ export class AttendanceCheckComponent implements OnInit {
this.router.navigate(['/attendance-dashboard/']);
return null
}
this.attendanceRegister = this.dashboardService.buildAttendanceReport(id, timestamp, currentClassId, grade, schoolName, schoolYear, reportDate, type, this.attendanceList);
const period = this.selectedPeriod;
this.attendanceRegister = this.dashboardService.buildAttendanceReport(id, timestamp, currentClassId, grade, schoolName, schoolYear, reportDate, type, this.attendanceList, period);
} else {
currentAttendanceReport.attendanceList = this.attendanceList
this.attendanceRegister = currentAttendanceReport
this.selectedPeriod = currentAttendanceReport.period
}
if (students.length > 0) {
await this.saveStudentAttendance()
}

}

async onPeriodChange($event) {
const period = $event.value
if (this.attendanceRegister) {
this.attendanceRegister.period = period
this.selectedPeriod = period
await this.saveStudentAttendance()
}
}

async toggleAttendance(currentStatus, student) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,11 @@ <h2>{{subtestReport.label}}</h2>
<td>
<span *ngFor="let res of generateArray(item.value)">
<ng-container *ngIf="res.value">
<ng-container *ngIf="res.value.percentage">
<ng-container *ngIf="res.value.percentage && !res.value.customScore">
({{tNumber(res.value.rawScore)}}/{{tNumber(res.value.totalGridAnswers)}}) {{tNumber(res.value.percentage)}}
</ng-container>
<ng-container *ngIf="!res.value.percentage">
({{tNumber(res.value.rawScore)}}/{{tNumber(res.value.totalGridAnswers)}})
<ng-container *ngIf="res.value.customScore||res.value.customScore===0">
{{(tNumber(res.value.customScore))|number : '1.2-2'}}%
</ng-container>
<!--<span *ngIf="res.value.totalCorrect">{{res.value.totalCorrect}}</span>-->
</ng-container>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,8 @@ export class StudentSubtestReportComponent implements OnInit, AfterViewChecked {
rawScore: result.score,
totalGridAnswers: result.maxValueAnswer,
percentage: percentage,
totalCorrect: totalCorrect
totalCorrect: totalCorrect,
customScore: result.customScore
};
resultObject[category] = scores;
const currentTotal = this.totals[category];
Expand Down
2 changes: 1 addition & 1 deletion editor/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
"redux": "^4.0.5",
"rxjs": "~6.5.5",
"rxjs-compat": "^6.5.5",
"tangy-form": "^4.45.1",
"tangy-form": "^4.45.4",
"tangy-form-editor": "7.18.0",
"translation-web-component": "0.0.3",
"tslib": "^1.11.2",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export class EventFormComponent implements OnInit, OnDestroy {
eventFormId: this.eventForm.id,
participantId: this.eventForm.participantId
}
this.formPlayer.render()
await this.formPlayer.render()

this.caseService.onChangeLocation$.subscribe(location => {
this.formPlayer.location = this.caseService.case.location
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,11 @@ export class IssueFormComponent implements OnInit {
this.caseService.setContext(this.issue.eventId, this.issue.eventFormId)
this.formPlayer.response = baseEvent.data.response
}
this.formPlayer.render()

// After render of the player, it will have created a new form response if one was not assigned.
// Make sure to save that new form response ID into the EventForm.
this.formPlayer.$rendered.subscribe(async () => {
if (!params.eventId) this.formPlayer.unlock()
})
const unlockFormResponse = !params.eventId
await this.formPlayer.render(unlockFormResponse)
this.formPlayer.$afterResubmit.subscribe(async () => {
const issueSaveProcess = this.pm.start('issue-save', 'Saving proposal...')
setTimeout(async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,17 @@ export class GroupDeviceUserComponent implements OnInit {
title = _TRANSLATE('Device User')
breadcrumbs:Array<Breadcrumb> = []
@ViewChild('formPlayer', {static: true}) formPlayer: TangyFormsPlayerComponent


responseId:string

constructor(
private route:ActivatedRoute,
private router:Router
) { }

ngOnInit() {
this.route.params.subscribe(params => {
this.responseId = params.responseId || ''
this.breadcrumbs = [
<Breadcrumb>{
label: _TRANSLATE('Device Users'),
Expand All @@ -32,13 +35,17 @@ export class GroupDeviceUserComponent implements OnInit {
url: `device-users/${params.responseId}`
}
]
this.formPlayer.formResponseId = params.responseId || ''
this.formPlayer.formId = 'user-profile'
this.formPlayer.preventSubmit = true
this.formPlayer.render()
this.formPlayer.$submit.subscribe(async () => {
this.router.navigate([`../`], { relativeTo: this.route })
})
this.ready();
})
}

async ready() {
this.formPlayer.formResponseId = this.responseId
this.formPlayer.formId = 'user-profile'
this.formPlayer.preventSubmit = true
await this.formPlayer.render()
this.formPlayer.$submit.subscribe(async () => {
this.router.navigate([`../`], { relativeTo: this.route })
})
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
<app-breadcrumb [title]="title" [breadcrumbs]="breadcrumbs"></app-breadcrumb>
<app-tangy-forms-player unlockFormResponses="true" #formPlayer></app-tangy-forms-player>
<app-tangy-forms-player [skipSaving]="true" #formPlayer></app-tangy-forms-player>
Loading

0 comments on commit a5422da

Please sign in to comment.