Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enabling metadata production for DataPipe; updated existing codebase to TypeScript and added miscellaneous functionalities. #99

Open
wants to merge 13 commits into
base: test
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .firebaserc
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@
},
"targets": {},
"etags": {}
}
}
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -147,3 +147,12 @@ osf-token-info.txt
.emulator-data

testServiceAccount.json

# TypeScript build artifacts
functions/lib/

#vscode local testing
.vscode/settings.json

#metadata build artifacts
functions/metadata/dist
2 changes: 1 addition & 1 deletion __tests__/validate-csv.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* @jest-environment node
*/

import validateCSV from "../functions/validate-csv";
import validateCSV from "../functions/lib/validate-csv.js";

describe("validateCSV", () => {
it("should return true when all required fields are present", () => {
Expand Down
2 changes: 1 addition & 1 deletion __tests__/validate-json.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* @jest-environment node
*/

import validateJSON from "../functions/validate-json";
import validateJSON from "../functions/lib/validate-json.js";

describe("validateJSON", () => {
it("should return true when all required fields are present", () => {
Expand Down
113 changes: 113 additions & 0 deletions components/dashboard/ErrorPanel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import {
FormControl,
FormLabel,
HStack,
Switch,
Stack,
Heading,
Accordion,
AccordionItem,
AccordionButton,
AccordionPanel,
AccordionIcon,
Alert,
AlertIcon,
AlertTitle,
AlertDescription,
Box,
Table,
Thead,
Tbody,
Tfoot,
Tr,
Th,
Td,
TableCaption,
TableContainer,
} from "@chakra-ui/react";

import { useState, useEffect } from "react";

import { setDoc, getDoc, doc } from "firebase/firestore";

import { db } from "../../lib/firebase";

export default function ErrorPanel({ errors }) {

return (
<Alert status="error" variant="solid">
<AlertIcon />
<Box flex="1">
<AlertTitle mb={4}>There was an error in data upload.</AlertTitle>
<Accordion allowToggle>
<AccordionItem>
<h2>
<AccordionButton>
<Box as="span" flex="1" textAlign="left">
See Error Logs
</Box>
</AccordionButton>
</h2>
<AccordionPanel pb={4}>
<TableContainer>
<Table variant='simple'>
<Thead>
<Tr>
<Th>ERROR</Th>
<Th>TIME</Th>
</Tr>
</Thead>
<Tbody>
{errors.map((error, index) => (
<Tr key={index}>
<Td>{error.error}</Td>
<Td>{error.time}</Td>
</Tr>))}
</Tbody>
</Table>
</TableContainer>
</AccordionPanel>
</AccordionItem>
</Accordion>
</Box>
</Alert>
);
}

async function toggleMetadataActive(expId, active) {
if (active) {
activateMetadata(expId);
} else {
deactivateMetadata(expId);
}
}

async function activateMetadata(expId) {
try {
await setDoc(
doc(db, `experiments/${expId}`),
{
metadataActive: true,
},
{ merge: true }
);
} catch (error) {
console.error(error);
}
}

async function deactivateMetadata(expId) {
try {
await setDoc(
doc(db, `experiments/${expId}`),
{
metadataActive: false,
},
{ merge: true }
);
} catch (error) {
console.error(error);
}
}


82 changes: 82 additions & 0 deletions components/dashboard/MetadataControl.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import {
FormControl,
FormLabel,
HStack,
Switch,
Stack,
Heading,
} from "@chakra-ui/react";

import { useState, useEffect } from "react";

import { setDoc, getDoc, doc } from "firebase/firestore";

import { db } from "../../lib/firebase";

export default function MetadataControl({ data }) {

const [metadataActive, setMetadataActive] = useState(data.metadataActive);

return (
<Stack
w="100%"
pr={8}
spacing={2}
bgColor={"black"}
borderRadius={16}
p={6}
>
<Heading fontSize="2xl">Metadata</Heading>
<FormControl as={HStack} justify="space-between" alignItems="center">
<FormLabel fontWeight={"normal"}>Enable Psych-DS metadata production?</FormLabel>
<Switch
colorScheme="green"
size="md"
isChecked={metadataActive}
onChange={(e) => {
setMetadataActive(e.target.checked);
toggleMetadataActive(data.id, e.target.checked);
}}
/>
</FormControl>
</Stack>
);
}

async function toggleMetadataActive(expId, active) {
if (active) {
activateMetadata(expId);
} else {
deactivateMetadata(expId);
}
}

async function activateMetadata(expId) {
try {
await setDoc(
doc(db, `experiments/${expId}`),
{
metadataActive: true,
},
{ merge: true }
);
} catch (error) {
console.error(error);
}
}

async function deactivateMetadata(expId) {
try {
await setDoc(
doc(db, `experiments/${expId}`),
{
metadataActive: false,
},
{ merge: true }
);
} catch (error) {
console.error(error);
}
}


30 changes: 26 additions & 4 deletions firebase.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,20 @@
},
"hosting": {
"source": ".",
"ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"rewrites": [
{
"source": "/api/data",
"function": "apidata"
},
{
"source": "/api/session",
"function": "apisession"
},
{
"source": "/api/condition",
"function": "apicondition"
Expand Down Expand Up @@ -42,7 +50,21 @@
"enabled": true
}
},
"functions": {
"source": "functions"
}
"functions": [
{
"source": "functions",
"codebase": "default",
"ignore": [
"node_modules",
".git",
"firebase-debug.log",
"firebase-debug.*.log",
"*.local"
],
"predeploy": [
"npm --prefix \"$RESOURCE_DIR\" run lint",
"npm --prefix \"$RESOURCE_DIR\" run build"
]
}
]
}
14 changes: 13 additions & 1 deletion firestore.rules
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ service cloud.firestore {
}
match /experiments/{experimentId} {
function verifyFields(){
return request.resource.data.keys().hasOnly(['active', 'activeBase64', 'activeConditionAssignment', 'id', 'osfRepo', 'osfComponent', 'osfFilesLink', 'owner', 'title', 'sessions', 'nConditions', 'currentCondition', 'useValidation', 'allowJSON', 'allowCSV', 'requiredFields', 'maxSessions', 'limitSessions'])
return request.resource.data.keys().hasOnly(['active', 'activeBase64', 'activeConditionAssignment', 'id', 'osfRepo', 'osfComponent', 'osfFilesLink', 'owner', 'title', 'sessions', 'nConditions', 'currentCondition', 'useValidation', 'allowJSON', 'allowCSV', 'requiredFields', 'maxSessions', 'limitSessions', 'metadata', 'metadataActive', 'incorrectMetadata'])
}
allow read: if(request.auth.uid != null) &&
resource.data.owner == request.auth.uid;
Expand All @@ -20,5 +20,17 @@ service cloud.firestore {
verifyFields();
allow delete: if(request.auth.uid == resource.data.owner);
}
match /metadata/{experimentId} {
Bankminer78 marked this conversation as resolved.
Show resolved Hide resolved
allow read: if(request.auth.uid != null) &&
resource.data.owner == request.auth.uid;
allow create: if(request.auth.uid != null) &&
resource.data.owner == request.auth.uid;
}
match /logs/{experimentId} {
Bankminer78 marked this conversation as resolved.
Show resolved Hide resolved
allow read: if(request.auth.uid != null) &&
resource.data.owner == request.auth.uid;
allow create: if(request.auth.uid != null) &&
resource.data.owner == request.auth.uid;
}
}
}
29 changes: 29 additions & 0 deletions functions/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
module.exports = {
root: true,
env: {
es6: true,
node: true,
},
extends: [
"eslint:recommended",
"plugin:import/errors",
"plugin:import/warnings",
"plugin:import/typescript",
"google",
"plugin:@typescript-eslint/recommended",
],
parser: "@typescript-eslint/parser",
parserOptions: {
project: ["tsconfig.json", "tsconfig.dev.json"],
sourceType: "module",
},
plugins: [
"@typescript-eslint",
"import",
],
rules: {
"quotes": ["error", "double"],
"import/no-unresolved": 0,
"indent": ["error", 2],
}
};
Loading