diff --git a/.gitignore b/.gitignore index 63dc29fef..89c8ded57 100644 --- a/.gitignore +++ b/.gitignore @@ -123,4 +123,5 @@ dmypy.json # End of https://www.gitignore.io/api/django # Editor settings -.vscode +.vscode +.idea/ diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index b2695a990..607016213 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -3,19 +3,12 @@ ## Develop with Docker (recommended quickstart) This is the simplest configuration for developers to start with. -### Initial Setup -1. Run `docker-compose run --rm django ./manage.py migrate` -2. Run `docker-compose run --rm django ./manage.py createcachetable` -3. Run `docker-compose run --rm django ./manage.py createsuperuser` - and follow the prompts to create your own user. - Set your username to your email to ensure parity with how GitHub logins work. -4. Run `docker-compose run --rm django ./manage.py create_dev_dandiset --owner your.email@email.com` - to create a dummy dandiset to start working with. +## Instructions for local development with front-end hot reloading -### Run Application -1. Run `docker-compose up` -2. Access the site, starting at http://localhost:8000/admin/ -3. When finished, use `Ctrl+C` +1. Ensure you have installed Docker on your local machine +2. Run `./admin_dev_startup.sh `. When prompted, enter an username and password in the command prompt. (If you run into local errors with the script, you may need to run `chmod +x admin_dev_startup.sh` first) +3. If not routed to `localhost:8000` upon clicking `LOG IN WITH GITHUB` (If routed appropriately, just log in), navigate to `localhost:8000/admin`, and log in with the username and password you used in Step #2. Under the `User` section, select the username and change the `Status` from `Incomplete` to `Approved`. +4. Return to `localhost:8085` and if not logged in yet, select `LOG IN WITH GITHUB`. ### Application Maintenance Occasionally, new package dependencies or schema changes will necessitate diff --git a/admin_dev_startup.sh b/admin_dev_startup.sh new file mode 100755 index 000000000..d37a644e3 --- /dev/null +++ b/admin_dev_startup.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +# This script can be used to launch both the frontend and backend with ease locally +# Happy developing! + +if [ $# -lt 2 ]; then + echo "Usage: $0 " + exit 1 +fi + +image_name=$1 +email=$2 + +cd web/ + +# Build Docker image (include the path to the Dockerfile's context) +docker build -t $image_name -f Dockerfile.dev . + +# Run the Docker container for frontend in background +docker run -d -v "$(pwd):/usr/src/app" -v /usr/src/app/node_modules -p 8085:8085 -e CHOKIDAR_USEPOLLING=true $image_name + +cd .. + +# Run Docker Compose commands for backend +docker compose run --rm django ./manage.py migrate +docker compose run --rm django ./manage.py createcachetable +docker compose run --rm django ./manage.py createsuperuser +docker compose run --rm django ./manage.py create_dev_dandiset --owner $email + +# Bring backend application to life! +docker compose up diff --git a/dandiapi/api/management/commands/create_dev_dandiset.py b/dandiapi/api/management/commands/create_dev_dandiset.py index a07bfdc40..057783520 100644 --- a/dandiapi/api/management/commands/create_dev_dandiset.py +++ b/dandiapi/api/management/commands/create_dev_dandiset.py @@ -1,3 +1,4 @@ +import hashlib from uuid import uuid4 from django.conf import settings @@ -15,8 +16,14 @@ @click.command() @click.option('--name', default='Development Dandiset') @click.option('--owner', 'email', required=True, help='The email address of the owner') -def create_dev_dandiset(*, name: str, email: str): - owner = User.objects.get(email=email) +@click.option('--first_name', default='Randi The Admin') +@click.option('--last_name', default='Dandi') +def create_dev_dandiset(name: str, email: str, first_name: str, last_name: str): + owner, is_created = User.objects.get_or_create(email=email) + if not is_created: + owner.first_name = first_name + owner.last_name = last_name + owner.save() version_metadata = { 'description': 'An informative description', @@ -26,16 +33,19 @@ def create_dev_dandiset(*, name: str, email: str): user=owner, embargo=False, version_name=name, version_metadata=version_metadata ) - uploaded_file = SimpleUploadedFile(name='foo/bar.txt', content=b'A' * 20) + file_size = 20 + file_content = b'A' * file_size + uploaded_file = SimpleUploadedFile(name='foo/bar.txt', content=file_content) etag = '76d36e98f312e98ff908c8c82c8dd623-0' + try: asset_blob = AssetBlob.objects.get(etag=etag) except AssetBlob.DoesNotExist: + # Since the SimpleUploadedFile is non-zarr asset, validation fails + # without a sha2_256 initially provided. + sha256_hash = hashlib.sha256(file_content).hexdigest() asset_blob = AssetBlob( - blob_id=uuid4(), - blob=uploaded_file, - etag=etag, - size=20, + blob_id=uuid4(), blob=uploaded_file, etag=etag, size=file_size, sha256=sha256_hash ) asset_blob.save() asset_metadata = { diff --git a/web/Dockerfile.dev b/web/Dockerfile.dev new file mode 100644 index 000000000..058e4b6b0 --- /dev/null +++ b/web/Dockerfile.dev @@ -0,0 +1,18 @@ +FROM node:20 + +# Set the working directory +WORKDIR /usr/src/app + +# Copy package.json and install dependencies +COPY package.json yarn.lock ./ +RUN yarn install --production=false + +# Copy the rest of your application's code +COPY . . + +# Expose the port the app runs on +EXPOSE 8085 + +# Start the application +CMD ["yarn", "run", "dev"] + diff --git a/web/package.json b/web/package.json index 9cf57db61..42e6356e4 100644 --- a/web/package.json +++ b/web/package.json @@ -2,7 +2,7 @@ "name": "dandi-archive", "version": "0.0.0", "scripts": { - "dev": "vite", + "dev": "vite --host 0.0.0.0", "build": "vite build", "preview": "vite preview --port 4173", "type-check": "vue-tsc --noEmit",