Skip to content

Commit

Permalink
Merge branch 'master' into hotfix/azure
Browse files Browse the repository at this point in the history
  • Loading branch information
devbtech authored Jun 8, 2022
2 parents 84731fd + cd8434e commit e3cfc7a
Show file tree
Hide file tree
Showing 19 changed files with 477 additions and 154 deletions.
24 changes: 24 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,30 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html)

## [0.17.0] - 2022-06-06
New Features:
- Welcome Applet: All accounts will now always have a Welcome applet shown on their device that contains almost all of the features MindLogger offers
- Cognitive Tasks: Flanker, CST, and A/B Trails activities can be added to applets via the applet builder or to the applet library. CST Gyroscope for Android devices is still being created and should not be used for research purposes
- Arbitrary Server: We now support GCP and Azure servers when connecting with our arbitrary server feature
- User Journey Export: The first version of our user journey timestamps export is available when exporting response data
- CST Editor: Editors can configure a CST activity within their activity

Improvements:
- Flanker:
The threshold to pass is updated to 75%
- CST Updates:
The slope calculation was updated to decrement the slope
Reset parameters at the end of the activity have been removed
- Reporting Update:
"Your child's score" was removed from the report PDF and replaced with Score

Bug Fixes:
- Transparent Images: Transparent images remain transparent when adding them to items in the applet builder
- Remove a user from an applet and data disappears: This has been fixed so that removing a user is only removing access and not data. The data missing previously from those accounts should be present now.

## [0.16.1] - 2022-05-18
- Fix variable name in cumulative score title

## [0.16.0] - 2022-05-9
New Features:
- One Page Assessment: Editors now have the ability to create a web-based assessment that will show all items on one page versus one item at a time
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "mindlogger-admin",
"version": "0.16.0",
"version": "0.17.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve --mode local",
Expand All @@ -22,7 +22,7 @@
"@sentry/browser": "^5.19.0",
"@sentry/integrations": "^5.19.0",
"@uiw/react-md-editor": "^3.0.7",
"applet-schema-builder": "^0.16.0",
"applet-schema-builder": "^0.17.1",
"aws-s3": "^2.0.5",
"aws-sdk": "^2.889.0",
"axios": "^0.21.1",
Expand Down
18 changes: 16 additions & 2 deletions src/Components/Applets/ActionButton.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,18 @@
<template v-slot:activator="{ on }">
<div v-on="on" >
<v-btn @click="$emit('click')" :disabled="disabled">
<v-icon :color="color" v-if="icon">{{icon}}</v-icon>
<img height="24" alt='' v-else v-bind:src="require(`@/assets/${imageName}`)"/>
<v-icon
v-if="icon"
:color="color"
:style="`transform: rotate(${rotation})`"
>{{icon}}</v-icon>
<img
v-else
height="24"
alt=''
:style="`transform: rotate(${rotation})`"
v-bind:src="require(`@/assets/${imageName}`)"
/>
</v-btn>
</div>
</template>
Expand Down Expand Up @@ -36,6 +46,10 @@
color: {
type: String,
default: 'secondary'
},
rotation: {
type: String,
default: '0deg'
}
}
}
Expand Down
27 changes: 27 additions & 0 deletions src/Components/Applets/AppletActions.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@
<action-button :tooltip="$t('editApplet')" icon="mdi-square-edit-outline" @click="onEditApplet(item)"
v-if="canEditApplet" :disabled="item.editing" />

<action-button :tooltip="$t('viewApplet')" icon="mdi-book-open-variant" @click="onEditApplet(item)"
v-if="!canEditApplet && item.welcomeApplet"
/>

<action-button :tooltip="$t('duplicateApplet')" imageName="copy-clipart.png" @click="onDuplicateApplet(item)"
v-if="canDuplicate" />
<action-button :tooltip="$t('deleteApplet')" icon="mdi-delete" @click="onDeleteApplet(item)"
Expand All @@ -27,6 +31,14 @@

<action-button :tooltip="$t('shareWithLibrary')" icon="mdi-web" @click="onShareWithLibrary"
v-if="canShareWithLibrary" />

<action-button
v-if="canCreateWelcomeApplet"
:tooltip="item.welcomeApplet ? $t('concealApplet') : $t('publishApplet')"
:rotation="item.welcomeApplet ? '180deg' : '0deg'"
icon="mdi-publish"
@click="onSwitchWelcomeApplet"
/>
</span>
<span class="laptop-hidden">
<v-menu offset-y>
Expand Down Expand Up @@ -76,6 +88,10 @@
<v-list-item v-if="canShareWithLibrary" @click="onShareWithLibrary">
<v-list-item-title>{{ $t('shareWithLibrary') }}</v-list-item-title>
</v-list-item>

<v-list-item v-if="canCreateWelcomeApplet" @click="onSwitchWelcomeApplet">
<v-list-item-title>{{ item.welcomeApplet ? $t('concealApplet') : $t('publishApplet') }}</v-list-item-title>
</v-list-item>
</v-list>
</v-menu>
</span>
Expand All @@ -98,6 +114,10 @@ export default {
}
},
computed : {
user() {
return this.$store.state.auth.user;
},
canViewUsers() {
return this.hasRoles(this.item, 'reviewer', 'manager', 'coordinator');
},
Expand Down Expand Up @@ -132,6 +152,10 @@ export default {
canShareWithLibrary() {
return this.hasRoles(this.item, 'owner', 'manager');
},
canCreateWelcomeApplet() {
return this.hasRoles(this.item, 'owner') && this.user && this.user.admin;
}
},
Expand Down Expand Up @@ -180,6 +204,9 @@ export default {
this.publishEvent("onShareWithLibrary");
},
onSwitchWelcomeApplet() {
this.publishEvent("onSwitchWelcomeApplet")
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions src/Components/Applets/AppletItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
@mouseover="appletHovered"
:class="{ 'drop-target': isDragOver }"
draggable
>
>
<template v-for="header in headers">
<td v-if="header.value !== 'actions'" :key="header.text" @click="appletClicked">
<div class="d-flex item">
Expand All @@ -18,7 +18,7 @@
<v-btn icon small depressed @click.stop="$emit('pinStatusChanged', item)" class="mr-3">
<v-icon color="primary" v-if="item.pinOrder > 0">mdi-pin</v-icon>
<v-icon color="#474747" v-else >mdi-pin-off</v-icon>
</v-btn>
</v-btn>
</div>
<div v-else :style="rowStyle">
<v-avatar color="blue" size="30" class="mr-2" style="color:white">
Expand All @@ -32,7 +32,7 @@
>
{{item.name[0]}}
</span>
</v-avatar>
</v-avatar>
</div>
</template>
<span v-if="header.value === 'updated'">
Expand Down
50 changes: 49 additions & 1 deletion src/Components/Applets/AppletList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,8 @@
@onRefreshApplet="onRefreshApplet"
@removeFromFolder="removeAppletFromFolder"
@onTransferOwnership="onTransferOwnership"
@onShareWithLibrary="onShareWithLibrary" />
@onShareWithLibrary="onShareWithLibrary"
@onSwitchWelcomeApplet="onSwitchWelcomeApplet" />
</template>
</applet-item>
</template>
Expand Down Expand Up @@ -165,6 +166,20 @@
@onOK="deleteFolderApplet"
/>

<ConfirmationDialog
v-model="welcomeAppletConfirmDialog"
:dialogText="$t('publishAppletConfirmation')"
:title="$t('publishApplet')"
@onOK="onSetWelcomeApplet(true)"
/>

<ConfirmationDialog
v-model="concealAppletConfirmationDialog"
:dialogText="$t('concealAppletConfirmation')"
:title="$t('concealApplet')"
@onOK="onSetWelcomeApplet(false)"
/>

<ConfirmationDialog
v-model="appletEditDialog"
:dialogText="$t('appletEditAlert')"
Expand Down Expand Up @@ -316,6 +331,8 @@ export default {
appletDeleteDialog: false,
folderAppletDelete: false,
appletPendingDelete: undefined,
welcomeAppletConfirmDialog: false,
concealAppletConfirmationDialog: false,
ownershipDialog: false,
shareWithDialog: false,
shareApplet: {},
Expand Down Expand Up @@ -656,6 +673,37 @@ export default {
});
},
onSetWelcomeApplet(publish=true) {
const item = this.visibleItems.find(item => item.id == this.hoveredAppletId);
this.welcomeAppletConfirmDialog = false;
this.concealAppletConfirmationDialog = false;
api
.setWelcomeAppletStatus({
apiHost: this.$store.state.backend,
token: this.$store.state.auth.authToken.token,
appletId: this.hoveredAppletId,
status: publish
})
.then(() => {
this.$emit("onSetWelcomeAppletSuccess", publish);
item.welcomeApplet = publish;
})
},
onSwitchWelcomeApplet(item) {
if (item.roles.includes('owner') && this.isNotEncrypted(item)) {
this.onUpdateAppletPassword(item);
} else {
if (item.welcomeApplet) {
this.concealAppletConfirmationDialog = true;
} else {
this.welcomeAppletConfirmDialog = true;
}
}
},
transferOwnership(ownershipEmail) {
api
.transferOwnership({
Expand Down
40 changes: 22 additions & 18 deletions src/Components/Builder/Builder.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
:cacheData="currentAppletBuilderData"
:basketApplets="basketApplets"
:themes="themes"
:viewMode="!canEditApplet"
@removeTemplate="onRemoveTemplate"
@updateTemplates="onAddTemplate"
@uploadProtocol="onUploadProtocol"
Expand Down Expand Up @@ -80,6 +81,7 @@ import axios from "axios";
import { mapState, mapGetters, mapMutations } from "vuex";
import { AppletMixin } from "../Utils/mixins/AppletMixin";
import { AccountMixin } from "../Utils/mixins/AccountMixin";
import { RolesMixin } from '../Utils/mixins/RolesMixin';
import encryption from "../Utils/encryption/encryption.vue";
import AppletPassword from "../Utils/dialogs/AppletPassword";
Expand All @@ -100,7 +102,7 @@ export default {
AppletPassword,
Information,
},
mixins: [AppletMixin, AccountMixin],
mixins: [AppletMixin, AccountMixin, RolesMixin],
data() {
return {
loading: true,
Expand Down Expand Up @@ -155,6 +157,9 @@ export default {
[]
);
},
canEditApplet() {
return !this.isEditing || (!this.currentAppletMeta.welcomeApplet || this.hasRoles(this.currentAppletMeta, 'owner'));
},
},
async beforeMount() {
const { apiHost, token } = this;
Expand Down Expand Up @@ -377,23 +382,22 @@ export default {
this.componentKey = this.componentKey + 1;
});
if (data.applet.publicLink) {
const inputTypes = ["radio", "checkbox", "slider", "text", "ageSelector", "dropdownList", "duration"]
const items = Object.values(data.items);
for (const item of items) {
const inputType = _.get(item, ['reprolib:terms/inputType', 0, '@value']);
if (!inputTypes.includes(inputType)) {
api.appletPublicLink({
method: "DELETE",
apiHost: apiHost,
token: token,
appletId
});
break;
}
}
}
// if (data.applet.publicLink) {
// const inputTypes = ["radio", "checkbox", "slider", "text", "ageSelector", "dropdownList", "duration"]
// const items = Object.values(data.items);
// for (const item of items) {
// const inputType = _.get(item, ['reprolib:terms/inputType', 0, '@value']);
// if (!inputTypes.includes(inputType)) {
// api.appletPublicLink({
// method: "DELETE",
// apiHost: apiHost,
// token: token,
// appletId
// });
// break;
// }
// }
// }
this.$store.commit("setBasketApplets", {});
this.$store.commit("cacheAppletBuilderData", null);
Expand Down
9 changes: 5 additions & 4 deletions src/Components/DataViewerComponents/CumulativeScore.vue
Original file line number Diff line number Diff line change
Expand Up @@ -128,19 +128,20 @@ export default {
const variableName = jsExpression.split(/[><]/g)[0];
const category = variableName.trim().replace(/\s/g, "__");
const scoreCategory = replaceItemVariableWithName(category, this.activity.items, rawResponses).replace(/\s/g, '__');
const expr = parser.parse(
category + jsExpression.substr(variableName.length)
scoreCategory + jsExpression.substr(variableName.length)
);
const variableScores = {
[category]: outputType == "percentage" ? Math.round(cumulativeMaxScores[category] ? cumulativeScores[category] * 100 / cumulativeMaxScores[category] : 0) : cumulativeScores[category]
[scoreCategory]: outputType == "percentage" ? Math.round(cumulativeMaxScores[category] ? cumulativeScores[category] * 100 / cumulativeMaxScores[category] : 0) : cumulativeScores[category]
}
if (expr.evaluate(variableScores)) {
reportMessages.push({
category,
category: scoreCategory,
message: replaceItemVariableWithName(message, this.activity.items, rawResponses),
score: variableScores[category] + (outputType == "percentage" ? "%" : ""),
score: variableScores[scoreCategory] + (outputType == "percentage" ? "%" : ""),
});
}
});
Expand Down
11 changes: 6 additions & 5 deletions src/Components/DataViewerComponents/CumulativeScoreReport.vue
Original file line number Diff line number Diff line change
Expand Up @@ -375,10 +375,11 @@ export default {
const variableName = exprArr[0];
const exprValue = parseFloat(exprArr[1].split(" ")[1]);
const category = variableName.trim().replace(/\s/g, "__");
const scoreCategory = replaceItemVariableWithName(category, activity.items, rawResponses).replace(/\s/g, '__');
let expr, key;
try {
expr = parser.parse(category + jsExpression.substr(variableName.length));
expr = parser.parse(scoreCategory + jsExpression.substr(variableName.length));
} catch (error) {
if (category.match(/[&\/\\#,+()$~%.'":*?<>{}]/g)) {
key = category.replace(/[&\/\\#,+()$~%.'":*?<>{}]/g, '');
Expand All @@ -387,7 +388,7 @@ export default {
}
const variableScores = {
[key ? key : category]:
[key ? key : scoreCategory]:
outputType == "percentage"
? Math.round(
cumulativeMaxScores[category] ? (cumulativeScores[category] * 100) / cumulativeMaxScores[category] : 0
Expand All @@ -403,9 +404,9 @@ export default {
);
reportMessages.push({
category,
category: scoreCategory,
message: replaceItemVariableWithName(message, activity.items, rawResponses),
score: variableScores[key ? key : category] + (outputType == "percentage" ? "%" : ""),
score: variableScores[key ? key : scoreCategory] + (outputType == "percentage" ? "%" : ""),
compute: {
...compute,
description: replaceItemVariableWithName(compute.description, activity.items, rawResponses)
Expand Down
1 change: 1 addition & 0 deletions src/Components/DataViewerComponents/Notes.vue
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ export default {
},
addComment() {
if (!this.comment || !this.comment.trim()) return;
api.addNote(this.apiHost, this.token, this.currentAppletMeta.id, this.responseId, this.comment).then(resp => {
this.notes.unshift(this.getNoteData(resp.data));
this.comment = '';
Expand Down
Loading

0 comments on commit e3cfc7a

Please sign in to comment.