From ff7b016190dd647b49d6e189359766e67706b6ff Mon Sep 17 00:00:00 2001 From: Danny Avila Date: Mon, 6 Mar 2023 12:49:22 -0500 Subject: [PATCH] initial docker detup --- .gitignore | 4 ++ api/.dockerignore | 2 + api/DockerFile | 2 +- api/app/detectCode.js | 16 +++---- {client/src/utils => api/app}/regexSplit.mjs | 0 client/.dockerignore | 2 + client/Dockerfile | 18 ++++++++ client/package.json | 2 +- .../components/Conversations/RenameButton.jsx | 2 +- client/src/store/convoSlice.js | 8 ++-- docker-compose.yml | 42 +++++++++++++++++++ 11 files changed, 84 insertions(+), 14 deletions(-) create mode 100644 api/.dockerignore rename {client/src/utils => api/app}/regexSplit.mjs (100%) create mode 100644 client/.dockerignore create mode 100644 client/Dockerfile create mode 100644 docker-compose.yml diff --git a/.gitignore b/.gitignore index 75ebce547d..b45375a167 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ ### node etc ### # Logs +data-node logs *.log @@ -24,6 +25,9 @@ dist/ public/main.js public/main.js.map public/main.js.LICENSE.txt +client/public/main.js +client/public/main.js.map +client/public/main.js.LICENSE.txt # Dependency directorys # Deployed apps should consider commenting these lines out: diff --git a/api/.dockerignore b/api/.dockerignore new file mode 100644 index 0000000000..7af7f04757 --- /dev/null +++ b/api/.dockerignore @@ -0,0 +1,2 @@ +/node_modules +.env \ No newline at end of file diff --git a/api/DockerFile b/api/DockerFile index 4088ad574d..decf59bc13 100644 --- a/api/DockerFile +++ b/api/DockerFile @@ -1,4 +1,4 @@ -FROM node:latest +FROM node:19-alpine WORKDIR /api # copy package.json into the container at /api COPY package*.json /api/ diff --git a/api/app/detectCode.js b/api/app/detectCode.js index 0ef6af31fc..5b7d213a67 100644 --- a/api/app/detectCode.js +++ b/api/app/detectCode.js @@ -16,10 +16,10 @@ const detectCode = async (text) => { // console.log('qualified for code match'); const modelOperations = new ModelOperations(); - const regexSplit = (await import('../src/utils/regexSplit.mjs')).default; + const regexSplit = (await import('./regexSplit.mjs')).default; const parts = regexSplit(text, codeRegex); - const output = parts.map(async (part, i) => { + const output = parts.map(async (part) => { if (part.match(codeRegex)) { const code = part.slice(3, -3); const language = await modelOperations.runModel(code); @@ -37,13 +37,13 @@ const detectCode = async (text) => { } }; -const example3 = { - text: "By default, the function generates an 8-character password with uppercase and lowercase letters and digits, but no special characters.\n\nTo use this function, simply call it with the desired arguments. For example:\n\n```\n>>> generate_password()\n'wE5pUxV7'\n>>> generate_password(length=12, special_chars=True)\n'M4v&^gJ*8#qH'\n>>> generate_password(uppercase=False, digits=False)\n'zajyprxr'\n``` \n\nNote that the randomness is used to select characters from the available character sets, but the resulting password is always deterministic given the same inputs. This makes the function useful for generating secure passwords that meet specific requirements." -}; +// const example3 = { +// text: "By default, the function generates an 8-character password with uppercase and lowercase letters and digits, but no special characters.\n\nTo use this function, simply call it with the desired arguments. For example:\n\n```\n>>> generate_password()\n'wE5pUxV7'\n>>> generate_password(length=12, special_chars=True)\n'M4v&^gJ*8#qH'\n>>> generate_password(uppercase=False, digits=False)\n'zajyprxr'\n``` \n\nNote that the randomness is used to select characters from the available character sets, but the resulting password is always deterministic given the same inputs. This makes the function useful for generating secure passwords that meet specific requirements." +// }; -const example4 = { - text: 'here\'s a cool function:\n```\nimport random\nimport string\n\ndef generate_password(length=8, uppercase=True, lowercase=True, digits=True, special_chars=False):\n """Generate a random password with specified requirements.\n\n Args:\n length (int): The length of the password. Default is 8.\n uppercase (bool): Whether to include uppercase letters. Default is True.\n lowercase (bool): Whether to include lowercase letters. Default is True.\n digits (bool): Whether to include digits. Default is True.\n special_chars (bool): Whether to include special characters. Default is False.\n\n Returns:\n str: A random password with the specified requirements.\n """\n # Define character sets to use in password generation\n chars = ""\n if uppercase:\n chars += string.ascii_uppercase\n if lowercase:\n chars += string.ascii_lowercase\n if digits:\n chars += string.digits\n if special_chars:\n chars += string.punctuation\n\n # Generate the password\n password = "".join(random.choice(chars) for _ in range(length))\n return password\n```\n\nThis function takes several arguments' -}; +// const example4 = { +// text: 'here\'s a cool function:\n```\nimport random\nimport string\n\ndef generate_password(length=8, uppercase=True, lowercase=True, digits=True, special_chars=False):\n """Generate a random password with specified requirements.\n\n Args:\n length (int): The length of the password. Default is 8.\n uppercase (bool): Whether to include uppercase letters. Default is True.\n lowercase (bool): Whether to include lowercase letters. Default is True.\n digits (bool): Whether to include digits. Default is True.\n special_chars (bool): Whether to include special characters. Default is False.\n\n Returns:\n str: A random password with the specified requirements.\n """\n # Define character sets to use in password generation\n chars = ""\n if uppercase:\n chars += string.ascii_uppercase\n if lowercase:\n chars += string.ascii_lowercase\n if digits:\n chars += string.digits\n if special_chars:\n chars += string.punctuation\n\n # Generate the password\n password = "".join(random.choice(chars) for _ in range(length))\n return password\n```\n\nThis function takes several arguments' +// }; // write an immediately invoked function to test this // (async () => { diff --git a/client/src/utils/regexSplit.mjs b/api/app/regexSplit.mjs similarity index 100% rename from client/src/utils/regexSplit.mjs rename to api/app/regexSplit.mjs diff --git a/client/.dockerignore b/client/.dockerignore new file mode 100644 index 0000000000..7af7f04757 --- /dev/null +++ b/client/.dockerignore @@ -0,0 +1,2 @@ +/node_modules +.env \ No newline at end of file diff --git a/client/Dockerfile b/client/Dockerfile new file mode 100644 index 0000000000..b39222e7ee --- /dev/null +++ b/client/Dockerfile @@ -0,0 +1,18 @@ +# Stage 1 +FROM node:19-alpine as builder +WORKDIR /client +# copy package.json into the container at /client +COPY package*.json /client/ +# install dependencies +RUN npm install +# Copy the current directory contents into the container at /client +COPY . /client/ +# Run the app when the container launches +CMD ["npm", "run", "build"] + +# Stage 2 +FROM nginx:stable-alpine +WORKDIR /usr/share/nginx/html +RUN rm -rf ./* +COPY --from=builder /client/public /usr/share/nginx/html +ENTRYPOINT ["nginx", "-g", "daemon off;"] diff --git a/client/package.json b/client/package.json index ec0eaf2109..4943a3c7dd 100644 --- a/client/package.json +++ b/client/package.json @@ -4,7 +4,7 @@ "description": "", "main": "index.js", "scripts": { - "build": "Webpack .", + "build": "webpack", "build-dev": "Webpack . --watch" }, "repository": { diff --git a/client/src/components/Conversations/RenameButton.jsx b/client/src/components/Conversations/RenameButton.jsx index d13a5e5db6..214d745f9b 100644 --- a/client/src/components/Conversations/RenameButton.jsx +++ b/client/src/components/Conversations/RenameButton.jsx @@ -2,7 +2,7 @@ import React from 'react'; import RenameIcon from '../svg/RenameIcon'; import CheckMark from '../svg/CheckMark'; -export default function RenameButton({ onClick, renaming, renameHandler, onRename }) { +export default function RenameButton({ renaming, renameHandler, onRename }) { const handler = renaming ? onRename : renameHandler; return ( diff --git a/client/src/store/convoSlice.js b/client/src/store/convoSlice.js index bb26a19347..167f712d07 100644 --- a/client/src/store/convoSlice.js +++ b/client/src/store/convoSlice.js @@ -12,7 +12,7 @@ const initialState = { promptPrefix: null, convosLoading: false, pageNumber: 1, - convos: [], + convos: [] }; const currentSlice = createSlice({ @@ -32,8 +32,10 @@ const currentSlice = createSlice({ const newConvos = action.payload.filter((convo) => { return !state.convos.some((c) => c.conversationId === convo.conversationId); }); - state.convos = [...state.convos, ...newConvos]; - }, + state.convos = [...state.convos, ...newConvos].sort( + (a, b) => new Date(b.created) - new Date(a.created) + ); + } } }); diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000000..666d6f2eeb --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,42 @@ +version: "2" + +services: + client: + image: react-app + restart: always + ports: + - "3000:3000" + volumes: + - ./client:/client + - /client/node_modules + links: + - api + networks: + - webappnetwork + api: + image: node-api + restart: always + ports: + - "9000:9000" + volumes: + - ./api:/api + - /api/node_modules + depends_on: + - mongodb + networks: + - webappnetwork + mongodb: + image: mongo + restart: always + container_name: mongodb + volumes: + - ./data-node:/data/db + ports: + - 27017:27017 + command: mongod --noauth + networks: + - webappnetwork + +networks: + webappnetwork: + driver: bridge \ No newline at end of file