AI-RESEARCHER-2024 commited on
Commit
4ec2f9d
·
verified ·
1 Parent(s): 8ecd942

add app files

Browse files
Files changed (38) hide show
  1. .gitattributes +2 -35
  2. .gitignore +33 -0
  3. .mvn/wrapper/maven-wrapper.properties +3 -0
  4. Dockerfile +30 -0
  5. mvnw +295 -0
  6. mvnw.cmd +189 -0
  7. pom.xml +114 -0
  8. src/main/java/com/creighton_theater/theater_database/PageController.java +146 -0
  9. src/main/java/com/creighton_theater/theater_database/TheaterDatabaseApplication.java +13 -0
  10. src/main/java/com/creighton_theater/theater_database/actorRestController.java +182 -0
  11. src/main/java/com/creighton_theater/theater_database/characterRestController.java +120 -0
  12. src/main/java/com/creighton_theater/theater_database/crewRestController.java +92 -0
  13. src/main/java/com/creighton_theater/theater_database/showRestController.java +43 -0
  14. src/main/java/com/creighton_theater/theater_database/studentRestController.java +66 -0
  15. src/main/resources/application.properties +21 -0
  16. src/main/resources/schema.sql +153 -0
  17. src/main/resources/static/actorScript.js +233 -0
  18. src/main/resources/static/characterScript.js +156 -0
  19. src/main/resources/static/crewScript.js +117 -0
  20. src/main/resources/static/script.js +183 -0
  21. src/main/resources/static/showScript.js +51 -0
  22. src/main/resources/static/studentScript.js +250 -0
  23. src/main/resources/static/style.css +387 -0
  24. src/main/resources/templates/actor/actors.html +65 -0
  25. src/main/resources/templates/actor/addActors.html +122 -0
  26. src/main/resources/templates/actor/editActor.html +153 -0
  27. src/main/resources/templates/characters/addCharacters.html +73 -0
  28. src/main/resources/templates/characters/character.html +41 -0
  29. src/main/resources/templates/crew/addCrew.html +70 -0
  30. src/main/resources/templates/crew/crew.html +46 -0
  31. src/main/resources/templates/help.html +11 -0
  32. src/main/resources/templates/index.html +20 -0
  33. src/main/resources/templates/shows/shows.html +34 -0
  34. src/main/resources/templates/student/addStudents.html +45 -0
  35. src/main/resources/templates/student/editStudents.html +49 -0
  36. src/main/resources/templates/student/students.html +42 -0
  37. src/main/todo.txt +21 -0
  38. src/test/java/com/creighton_theater/theater_database/TheaterDatabaseApplicationTests.java +13 -0
.gitattributes CHANGED
@@ -1,35 +1,2 @@
1
- *.7z filter=lfs diff=lfs merge=lfs -text
2
- *.arrow filter=lfs diff=lfs merge=lfs -text
3
- *.bin filter=lfs diff=lfs merge=lfs -text
4
- *.bz2 filter=lfs diff=lfs merge=lfs -text
5
- *.ckpt filter=lfs diff=lfs merge=lfs -text
6
- *.ftz filter=lfs diff=lfs merge=lfs -text
7
- *.gz filter=lfs diff=lfs merge=lfs -text
8
- *.h5 filter=lfs diff=lfs merge=lfs -text
9
- *.joblib filter=lfs diff=lfs merge=lfs -text
10
- *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
- *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
- *.model filter=lfs diff=lfs merge=lfs -text
13
- *.msgpack filter=lfs diff=lfs merge=lfs -text
14
- *.npy filter=lfs diff=lfs merge=lfs -text
15
- *.npz filter=lfs diff=lfs merge=lfs -text
16
- *.onnx filter=lfs diff=lfs merge=lfs -text
17
- *.ot filter=lfs diff=lfs merge=lfs -text
18
- *.parquet filter=lfs diff=lfs merge=lfs -text
19
- *.pb filter=lfs diff=lfs merge=lfs -text
20
- *.pickle filter=lfs diff=lfs merge=lfs -text
21
- *.pkl filter=lfs diff=lfs merge=lfs -text
22
- *.pt filter=lfs diff=lfs merge=lfs -text
23
- *.pth filter=lfs diff=lfs merge=lfs -text
24
- *.rar filter=lfs diff=lfs merge=lfs -text
25
- *.safetensors filter=lfs diff=lfs merge=lfs -text
26
- saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
- *.tar.* filter=lfs diff=lfs merge=lfs -text
28
- *.tar filter=lfs diff=lfs merge=lfs -text
29
- *.tflite filter=lfs diff=lfs merge=lfs -text
30
- *.tgz filter=lfs diff=lfs merge=lfs -text
31
- *.wasm filter=lfs diff=lfs merge=lfs -text
32
- *.xz filter=lfs diff=lfs merge=lfs -text
33
- *.zip filter=lfs diff=lfs merge=lfs -text
34
- *.zst filter=lfs diff=lfs merge=lfs -text
35
- *tfevents* filter=lfs diff=lfs merge=lfs -text
 
1
+ /mvnw text eol=lf
2
+ *.cmd text eol=crlf
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
.gitignore ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ HELP.md
2
+ target/
3
+ .mvn/wrapper/maven-wrapper.jar
4
+ !**/src/main/**/target/
5
+ !**/src/test/**/target/
6
+
7
+ ### STS ###
8
+ .apt_generated
9
+ .classpath
10
+ .factorypath
11
+ .project
12
+ .settings
13
+ .springBeans
14
+ .sts4-cache
15
+
16
+ ### IntelliJ IDEA ###
17
+ .idea
18
+ *.iws
19
+ *.iml
20
+ *.ipr
21
+
22
+ ### NetBeans ###
23
+ /nbproject/private/
24
+ /nbbuild/
25
+ /dist/
26
+ /nbdist/
27
+ /.nb-gradle/
28
+ build/
29
+ !**/src/main/**/build/
30
+ !**/src/test/**/build/
31
+
32
+ ### VS Code ###
33
+ .vscode/
.mvn/wrapper/maven-wrapper.properties ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ wrapperVersion=3.3.4
2
+ distributionType=only-script
3
+ distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.11/apache-maven-3.9.11-bin.zip
Dockerfile ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Use Maven image to build the application
2
+ FROM maven:3.9-eclipse-temurin-21 AS build
3
+
4
+ # Set working directory
5
+ WORKDIR /app
6
+
7
+ # Copy pom.xml and download dependencies
8
+ COPY pom.xml .
9
+ RUN mvn dependency:go-offline
10
+
11
+ # Copy source code
12
+ COPY src ./src
13
+
14
+ # Build the application
15
+ RUN mvn clean package -DskipTests
16
+
17
+ # Use JRE for runtime
18
+ FROM eclipse-temurin:21-jre
19
+
20
+ # Set working directory
21
+ WORKDIR /app
22
+
23
+ # Copy the jar from build stage
24
+ COPY --from=build /app/target/*.jar app.jar
25
+
26
+ # Expose port 7860 (Hugging Face Spaces default)
27
+ EXPOSE 7860
28
+
29
+ # Run the application
30
+ ENTRYPOINT ["java", "-jar", "app.jar"]
mvnw ADDED
@@ -0,0 +1,295 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/sh
2
+ # ----------------------------------------------------------------------------
3
+ # Licensed to the Apache Software Foundation (ASF) under one
4
+ # or more contributor license agreements. See the NOTICE file
5
+ # distributed with this work for additional information
6
+ # regarding copyright ownership. The ASF licenses this file
7
+ # to you under the Apache License, Version 2.0 (the
8
+ # "License"); you may not use this file except in compliance
9
+ # with the License. You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing,
14
+ # software distributed under the License is distributed on an
15
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16
+ # KIND, either express or implied. See the License for the
17
+ # specific language governing permissions and limitations
18
+ # under the License.
19
+ # ----------------------------------------------------------------------------
20
+
21
+ # ----------------------------------------------------------------------------
22
+ # Apache Maven Wrapper startup batch script, version 3.3.4
23
+ #
24
+ # Optional ENV vars
25
+ # -----------------
26
+ # JAVA_HOME - location of a JDK home dir, required when download maven via java source
27
+ # MVNW_REPOURL - repo url base for downloading maven distribution
28
+ # MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven
29
+ # MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output
30
+ # ----------------------------------------------------------------------------
31
+
32
+ set -euf
33
+ [ "${MVNW_VERBOSE-}" != debug ] || set -x
34
+
35
+ # OS specific support.
36
+ native_path() { printf %s\\n "$1"; }
37
+ case "$(uname)" in
38
+ CYGWIN* | MINGW*)
39
+ [ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")"
40
+ native_path() { cygpath --path --windows "$1"; }
41
+ ;;
42
+ esac
43
+
44
+ # set JAVACMD and JAVACCMD
45
+ set_java_home() {
46
+ # For Cygwin and MinGW, ensure paths are in Unix format before anything is touched
47
+ if [ -n "${JAVA_HOME-}" ]; then
48
+ if [ -x "$JAVA_HOME/jre/sh/java" ]; then
49
+ # IBM's JDK on AIX uses strange locations for the executables
50
+ JAVACMD="$JAVA_HOME/jre/sh/java"
51
+ JAVACCMD="$JAVA_HOME/jre/sh/javac"
52
+ else
53
+ JAVACMD="$JAVA_HOME/bin/java"
54
+ JAVACCMD="$JAVA_HOME/bin/javac"
55
+
56
+ if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then
57
+ echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2
58
+ echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2
59
+ return 1
60
+ fi
61
+ fi
62
+ else
63
+ JAVACMD="$(
64
+ 'set' +e
65
+ 'unset' -f command 2>/dev/null
66
+ 'command' -v java
67
+ )" || :
68
+ JAVACCMD="$(
69
+ 'set' +e
70
+ 'unset' -f command 2>/dev/null
71
+ 'command' -v javac
72
+ )" || :
73
+
74
+ if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then
75
+ echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2
76
+ return 1
77
+ fi
78
+ fi
79
+ }
80
+
81
+ # hash string like Java String::hashCode
82
+ hash_string() {
83
+ str="${1:-}" h=0
84
+ while [ -n "$str" ]; do
85
+ char="${str%"${str#?}"}"
86
+ h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296))
87
+ str="${str#?}"
88
+ done
89
+ printf %x\\n $h
90
+ }
91
+
92
+ verbose() { :; }
93
+ [ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; }
94
+
95
+ die() {
96
+ printf %s\\n "$1" >&2
97
+ exit 1
98
+ }
99
+
100
+ trim() {
101
+ # MWRAPPER-139:
102
+ # Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds.
103
+ # Needed for removing poorly interpreted newline sequences when running in more
104
+ # exotic environments such as mingw bash on Windows.
105
+ printf "%s" "${1}" | tr -d '[:space:]'
106
+ }
107
+
108
+ scriptDir="$(dirname "$0")"
109
+ scriptName="$(basename "$0")"
110
+
111
+ # parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties
112
+ while IFS="=" read -r key value; do
113
+ case "${key-}" in
114
+ distributionUrl) distributionUrl=$(trim "${value-}") ;;
115
+ distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;;
116
+ esac
117
+ done <"$scriptDir/.mvn/wrapper/maven-wrapper.properties"
118
+ [ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties"
119
+
120
+ case "${distributionUrl##*/}" in
121
+ maven-mvnd-*bin.*)
122
+ MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/
123
+ case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in
124
+ *AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;;
125
+ :Darwin*x86_64) distributionPlatform=darwin-amd64 ;;
126
+ :Darwin*arm64) distributionPlatform=darwin-aarch64 ;;
127
+ :Linux*x86_64*) distributionPlatform=linux-amd64 ;;
128
+ *)
129
+ echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2
130
+ distributionPlatform=linux-amd64
131
+ ;;
132
+ esac
133
+ distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip"
134
+ ;;
135
+ maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;;
136
+ *) MVN_CMD="mvn${scriptName#mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;;
137
+ esac
138
+
139
+ # apply MVNW_REPOURL and calculate MAVEN_HOME
140
+ # maven home pattern: ~/.m2/wrapper/dists/{apache-maven-<version>,maven-mvnd-<version>-<platform>}/<hash>
141
+ [ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}"
142
+ distributionUrlName="${distributionUrl##*/}"
143
+ distributionUrlNameMain="${distributionUrlName%.*}"
144
+ distributionUrlNameMain="${distributionUrlNameMain%-bin}"
145
+ MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}"
146
+ MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")"
147
+
148
+ exec_maven() {
149
+ unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || :
150
+ exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD"
151
+ }
152
+
153
+ if [ -d "$MAVEN_HOME" ]; then
154
+ verbose "found existing MAVEN_HOME at $MAVEN_HOME"
155
+ exec_maven "$@"
156
+ fi
157
+
158
+ case "${distributionUrl-}" in
159
+ *?-bin.zip | *?maven-mvnd-?*-?*.zip) ;;
160
+ *) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;;
161
+ esac
162
+
163
+ # prepare tmp dir
164
+ if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then
165
+ clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; }
166
+ trap clean HUP INT TERM EXIT
167
+ else
168
+ die "cannot create temp dir"
169
+ fi
170
+
171
+ mkdir -p -- "${MAVEN_HOME%/*}"
172
+
173
+ # Download and Install Apache Maven
174
+ verbose "Couldn't find MAVEN_HOME, downloading and installing it ..."
175
+ verbose "Downloading from: $distributionUrl"
176
+ verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName"
177
+
178
+ # select .zip or .tar.gz
179
+ if ! command -v unzip >/dev/null; then
180
+ distributionUrl="${distributionUrl%.zip}.tar.gz"
181
+ distributionUrlName="${distributionUrl##*/}"
182
+ fi
183
+
184
+ # verbose opt
185
+ __MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR=''
186
+ [ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v
187
+
188
+ # normalize http auth
189
+ case "${MVNW_PASSWORD:+has-password}" in
190
+ '') MVNW_USERNAME='' MVNW_PASSWORD='' ;;
191
+ has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;;
192
+ esac
193
+
194
+ if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then
195
+ verbose "Found wget ... using wget"
196
+ wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl"
197
+ elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then
198
+ verbose "Found curl ... using curl"
199
+ curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl"
200
+ elif set_java_home; then
201
+ verbose "Falling back to use Java to download"
202
+ javaSource="$TMP_DOWNLOAD_DIR/Downloader.java"
203
+ targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName"
204
+ cat >"$javaSource" <<-END
205
+ public class Downloader extends java.net.Authenticator
206
+ {
207
+ protected java.net.PasswordAuthentication getPasswordAuthentication()
208
+ {
209
+ return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() );
210
+ }
211
+ public static void main( String[] args ) throws Exception
212
+ {
213
+ setDefault( new Downloader() );
214
+ java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() );
215
+ }
216
+ }
217
+ END
218
+ # For Cygwin/MinGW, switch paths to Windows format before running javac and java
219
+ verbose " - Compiling Downloader.java ..."
220
+ "$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java"
221
+ verbose " - Running Downloader.java ..."
222
+ "$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")"
223
+ fi
224
+
225
+ # If specified, validate the SHA-256 sum of the Maven distribution zip file
226
+ if [ -n "${distributionSha256Sum-}" ]; then
227
+ distributionSha256Result=false
228
+ if [ "$MVN_CMD" = mvnd.sh ]; then
229
+ echo "Checksum validation is not supported for maven-mvnd." >&2
230
+ echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2
231
+ exit 1
232
+ elif command -v sha256sum >/dev/null; then
233
+ if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c - >/dev/null 2>&1; then
234
+ distributionSha256Result=true
235
+ fi
236
+ elif command -v shasum >/dev/null; then
237
+ if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then
238
+ distributionSha256Result=true
239
+ fi
240
+ else
241
+ echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2
242
+ echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2
243
+ exit 1
244
+ fi
245
+ if [ $distributionSha256Result = false ]; then
246
+ echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2
247
+ echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2
248
+ exit 1
249
+ fi
250
+ fi
251
+
252
+ # unzip and move
253
+ if command -v unzip >/dev/null; then
254
+ unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip"
255
+ else
256
+ tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar"
257
+ fi
258
+
259
+ # Find the actual extracted directory name (handles snapshots where filename != directory name)
260
+ actualDistributionDir=""
261
+
262
+ # First try the expected directory name (for regular distributions)
263
+ if [ -d "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" ]; then
264
+ if [ -f "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/bin/$MVN_CMD" ]; then
265
+ actualDistributionDir="$distributionUrlNameMain"
266
+ fi
267
+ fi
268
+
269
+ # If not found, search for any directory with the Maven executable (for snapshots)
270
+ if [ -z "$actualDistributionDir" ]; then
271
+ # enable globbing to iterate over items
272
+ set +f
273
+ for dir in "$TMP_DOWNLOAD_DIR"/*; do
274
+ if [ -d "$dir" ]; then
275
+ if [ -f "$dir/bin/$MVN_CMD" ]; then
276
+ actualDistributionDir="$(basename "$dir")"
277
+ break
278
+ fi
279
+ fi
280
+ done
281
+ set -f
282
+ fi
283
+
284
+ if [ -z "$actualDistributionDir" ]; then
285
+ verbose "Contents of $TMP_DOWNLOAD_DIR:"
286
+ verbose "$(ls -la "$TMP_DOWNLOAD_DIR")"
287
+ die "Could not find Maven distribution directory in extracted archive"
288
+ fi
289
+
290
+ verbose "Found extracted Maven distribution directory: $actualDistributionDir"
291
+ printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$actualDistributionDir/mvnw.url"
292
+ mv -- "$TMP_DOWNLOAD_DIR/$actualDistributionDir" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME"
293
+
294
+ clean || :
295
+ exec_maven "$@"
mvnw.cmd ADDED
@@ -0,0 +1,189 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <# : batch portion
2
+ @REM ----------------------------------------------------------------------------
3
+ @REM Licensed to the Apache Software Foundation (ASF) under one
4
+ @REM or more contributor license agreements. See the NOTICE file
5
+ @REM distributed with this work for additional information
6
+ @REM regarding copyright ownership. The ASF licenses this file
7
+ @REM to you under the Apache License, Version 2.0 (the
8
+ @REM "License"); you may not use this file except in compliance
9
+ @REM with the License. You may obtain a copy of the License at
10
+ @REM
11
+ @REM http://www.apache.org/licenses/LICENSE-2.0
12
+ @REM
13
+ @REM Unless required by applicable law or agreed to in writing,
14
+ @REM software distributed under the License is distributed on an
15
+ @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16
+ @REM KIND, either express or implied. See the License for the
17
+ @REM specific language governing permissions and limitations
18
+ @REM under the License.
19
+ @REM ----------------------------------------------------------------------------
20
+
21
+ @REM ----------------------------------------------------------------------------
22
+ @REM Apache Maven Wrapper startup batch script, version 3.3.4
23
+ @REM
24
+ @REM Optional ENV vars
25
+ @REM MVNW_REPOURL - repo url base for downloading maven distribution
26
+ @REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven
27
+ @REM MVNW_VERBOSE - true: enable verbose log; others: silence the output
28
+ @REM ----------------------------------------------------------------------------
29
+
30
+ @IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0)
31
+ @SET __MVNW_CMD__=
32
+ @SET __MVNW_ERROR__=
33
+ @SET __MVNW_PSMODULEP_SAVE=%PSModulePath%
34
+ @SET PSModulePath=
35
+ @FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @(
36
+ IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B)
37
+ )
38
+ @SET PSModulePath=%__MVNW_PSMODULEP_SAVE%
39
+ @SET __MVNW_PSMODULEP_SAVE=
40
+ @SET __MVNW_ARG0_NAME__=
41
+ @SET MVNW_USERNAME=
42
+ @SET MVNW_PASSWORD=
43
+ @IF NOT "%__MVNW_CMD__%"=="" ("%__MVNW_CMD__%" %*)
44
+ @echo Cannot start maven from wrapper >&2 && exit /b 1
45
+ @GOTO :EOF
46
+ : end batch / begin powershell #>
47
+
48
+ $ErrorActionPreference = "Stop"
49
+ if ($env:MVNW_VERBOSE -eq "true") {
50
+ $VerbosePreference = "Continue"
51
+ }
52
+
53
+ # calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties
54
+ $distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl
55
+ if (!$distributionUrl) {
56
+ Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties"
57
+ }
58
+
59
+ switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) {
60
+ "maven-mvnd-*" {
61
+ $USE_MVND = $true
62
+ $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip"
63
+ $MVN_CMD = "mvnd.cmd"
64
+ break
65
+ }
66
+ default {
67
+ $USE_MVND = $false
68
+ $MVN_CMD = $script -replace '^mvnw','mvn'
69
+ break
70
+ }
71
+ }
72
+
73
+ # apply MVNW_REPOURL and calculate MAVEN_HOME
74
+ # maven home pattern: ~/.m2/wrapper/dists/{apache-maven-<version>,maven-mvnd-<version>-<platform>}/<hash>
75
+ if ($env:MVNW_REPOURL) {
76
+ $MVNW_REPO_PATTERN = if ($USE_MVND -eq $False) { "/org/apache/maven/" } else { "/maven/mvnd/" }
77
+ $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace "^.*$MVNW_REPO_PATTERN",'')"
78
+ }
79
+ $distributionUrlName = $distributionUrl -replace '^.*/',''
80
+ $distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$',''
81
+
82
+ $MAVEN_M2_PATH = "$HOME/.m2"
83
+ if ($env:MAVEN_USER_HOME) {
84
+ $MAVEN_M2_PATH = "$env:MAVEN_USER_HOME"
85
+ }
86
+
87
+ if (-not (Test-Path -Path $MAVEN_M2_PATH)) {
88
+ New-Item -Path $MAVEN_M2_PATH -ItemType Directory | Out-Null
89
+ }
90
+
91
+ $MAVEN_WRAPPER_DISTS = $null
92
+ if ((Get-Item $MAVEN_M2_PATH).Target[0] -eq $null) {
93
+ $MAVEN_WRAPPER_DISTS = "$MAVEN_M2_PATH/wrapper/dists"
94
+ } else {
95
+ $MAVEN_WRAPPER_DISTS = (Get-Item $MAVEN_M2_PATH).Target[0] + "/wrapper/dists"
96
+ }
97
+
98
+ $MAVEN_HOME_PARENT = "$MAVEN_WRAPPER_DISTS/$distributionUrlNameMain"
99
+ $MAVEN_HOME_NAME = ([System.Security.Cryptography.SHA256]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join ''
100
+ $MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME"
101
+
102
+ if (Test-Path -Path "$MAVEN_HOME" -PathType Container) {
103
+ Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME"
104
+ Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD"
105
+ exit $?
106
+ }
107
+
108
+ if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) {
109
+ Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl"
110
+ }
111
+
112
+ # prepare tmp dir
113
+ $TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile
114
+ $TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir"
115
+ $TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null
116
+ trap {
117
+ if ($TMP_DOWNLOAD_DIR.Exists) {
118
+ try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null }
119
+ catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" }
120
+ }
121
+ }
122
+
123
+ New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null
124
+
125
+ # Download and Install Apache Maven
126
+ Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..."
127
+ Write-Verbose "Downloading from: $distributionUrl"
128
+ Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName"
129
+
130
+ $webclient = New-Object System.Net.WebClient
131
+ if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) {
132
+ $webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD)
133
+ }
134
+ [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
135
+ $webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null
136
+
137
+ # If specified, validate the SHA-256 sum of the Maven distribution zip file
138
+ $distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum
139
+ if ($distributionSha256Sum) {
140
+ if ($USE_MVND) {
141
+ Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties."
142
+ }
143
+ Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash
144
+ if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) {
145
+ Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property."
146
+ }
147
+ }
148
+
149
+ # unzip and move
150
+ Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null
151
+
152
+ # Find the actual extracted directory name (handles snapshots where filename != directory name)
153
+ $actualDistributionDir = ""
154
+
155
+ # First try the expected directory name (for regular distributions)
156
+ $expectedPath = Join-Path "$TMP_DOWNLOAD_DIR" "$distributionUrlNameMain"
157
+ $expectedMvnPath = Join-Path "$expectedPath" "bin/$MVN_CMD"
158
+ if ((Test-Path -Path $expectedPath -PathType Container) -and (Test-Path -Path $expectedMvnPath -PathType Leaf)) {
159
+ $actualDistributionDir = $distributionUrlNameMain
160
+ }
161
+
162
+ # If not found, search for any directory with the Maven executable (for snapshots)
163
+ if (!$actualDistributionDir) {
164
+ Get-ChildItem -Path "$TMP_DOWNLOAD_DIR" -Directory | ForEach-Object {
165
+ $testPath = Join-Path $_.FullName "bin/$MVN_CMD"
166
+ if (Test-Path -Path $testPath -PathType Leaf) {
167
+ $actualDistributionDir = $_.Name
168
+ }
169
+ }
170
+ }
171
+
172
+ if (!$actualDistributionDir) {
173
+ Write-Error "Could not find Maven distribution directory in extracted archive"
174
+ }
175
+
176
+ Write-Verbose "Found extracted Maven distribution directory: $actualDistributionDir"
177
+ Rename-Item -Path "$TMP_DOWNLOAD_DIR/$actualDistributionDir" -NewName $MAVEN_HOME_NAME | Out-Null
178
+ try {
179
+ Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null
180
+ } catch {
181
+ if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) {
182
+ Write-Error "fail to move MAVEN_HOME"
183
+ }
184
+ } finally {
185
+ try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null }
186
+ catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" }
187
+ }
188
+
189
+ Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD"
pom.xml ADDED
@@ -0,0 +1,114 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4
+ <modelVersion>4.0.0</modelVersion>
5
+ <parent>
6
+ <groupId>org.springframework.boot</groupId>
7
+ <artifactId>spring-boot-starter-parent</artifactId>
8
+ <version>3.5.7</version>
9
+ <relativePath/> <!-- lookup parent from repository -->
10
+ </parent>
11
+ <groupId>com.creighton_theater</groupId>
12
+ <artifactId>theater_database</artifactId>
13
+ <version>0.0.1-SNAPSHOT</version>
14
+ <name>theater_database</name>
15
+ <description>Demo project for Spring Boot</description>
16
+ <url/>
17
+ <licenses>
18
+ <license/>
19
+ </licenses>
20
+ <developers>
21
+ <developer/>
22
+ </developers>
23
+ <scm>
24
+ <connection/>
25
+ <developerConnection/>
26
+ <tag/>
27
+ <url/>
28
+ </scm>
29
+ <properties>
30
+ <java.version>25</java.version>
31
+ </properties>
32
+ <dependencies>
33
+ <dependency>
34
+ <groupId>org.springframework.boot</groupId>
35
+ <artifactId>spring-boot-starter-jdbc</artifactId>
36
+ </dependency>
37
+ <dependency>
38
+ <groupId>org.springframework.boot</groupId>
39
+ <artifactId>spring-boot-starter-data-jpa</artifactId>
40
+ </dependency>
41
+ <dependency>
42
+ <groupId>org.springframework.boot</groupId>
43
+ <artifactId>spring-boot-starter-thymeleaf</artifactId>
44
+ </dependency>
45
+ <dependency>
46
+ <groupId>org.springframework.boot</groupId>
47
+ <artifactId>spring-boot-starter-web</artifactId>
48
+ </dependency>
49
+
50
+ <dependency>
51
+ <groupId>org.springframework.boot</groupId>
52
+ <artifactId>spring-boot-devtools</artifactId>
53
+ <scope>runtime</scope>
54
+ <optional>true</optional>
55
+ </dependency>
56
+ <!-- MySQL for local development -->
57
+ <dependency>
58
+ <groupId>com.mysql</groupId>
59
+ <artifactId>mysql-connector-j</artifactId>
60
+ <scope>runtime</scope>
61
+ <optional>true</optional>
62
+ </dependency>
63
+ <!-- H2 Database for Hugging Face Spaces deployment -->
64
+ <dependency>
65
+ <groupId>com.h2database</groupId>
66
+ <artifactId>h2</artifactId>
67
+ <scope>runtime</scope>
68
+ </dependency>
69
+ <dependency>
70
+ <groupId>org.projectlombok</groupId>
71
+ <artifactId>lombok</artifactId>
72
+ <optional>true</optional>
73
+ </dependency>
74
+ <dependency>
75
+ <groupId>org.springframework.boot</groupId>
76
+ <artifactId>spring-boot-starter-test</artifactId>
77
+ <scope>test</scope>
78
+ </dependency>
79
+ <dependency>
80
+ <groupId>org.springframework.boot</groupId>
81
+ <artifactId>spring-boot-starter-thymeleaf</artifactId>
82
+ </dependency>
83
+ </dependencies>
84
+
85
+ <build>
86
+ <plugins>
87
+ <plugin>
88
+ <groupId>org.apache.maven.plugins</groupId>
89
+ <artifactId>maven-compiler-plugin</artifactId>
90
+ <configuration>
91
+ <annotationProcessorPaths>
92
+ <path>
93
+ <groupId>org.projectlombok</groupId>
94
+ <artifactId>lombok</artifactId>
95
+ </path>
96
+ </annotationProcessorPaths>
97
+ </configuration>
98
+ </plugin>
99
+ <plugin>
100
+ <groupId>org.springframework.boot</groupId>
101
+ <artifactId>spring-boot-maven-plugin</artifactId>
102
+ <configuration>
103
+ <excludes>
104
+ <exclude>
105
+ <groupId>org.projectlombok</groupId>
106
+ <artifactId>lombok</artifactId>
107
+ </exclude>
108
+ </excludes>
109
+ </configuration>
110
+ </plugin>
111
+ </plugins>
112
+ </build>
113
+
114
+ </project>
src/main/java/com/creighton_theater/theater_database/PageController.java ADDED
@@ -0,0 +1,146 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package com.creighton_theater.theater_database;
2
+
3
+ import java.util.List;
4
+ import java.util.Map;
5
+
6
+ import org.springframework.beans.factory.annotation.Autowired;
7
+ import org.springframework.jdbc.core.JdbcTemplate;
8
+ import org.springframework.stereotype.Controller;
9
+ import org.springframework.ui.Model;
10
+ import org.springframework.web.bind.annotation.GetMapping;
11
+ import org.springframework.web.bind.annotation.PathVariable;
12
+ import org.springframework.web.bind.annotation.RequestParam;
13
+
14
+ @Controller
15
+ public class PageController {
16
+
17
+ @Autowired
18
+ private JdbcTemplate jdbcTemplate;
19
+
20
+ @GetMapping("/")
21
+ public String landingPage() {
22
+ return "index";
23
+ }
24
+
25
+ @GetMapping("/help")
26
+ public String helpPage() {
27
+ return "help";
28
+ }
29
+
30
+ @GetMapping("/student/loadpage")
31
+ public String studentPage() {
32
+ return "student/students";
33
+ }
34
+
35
+ @GetMapping("/addStudent")
36
+ public String addStudentPage() {
37
+ return "student/addStudents";
38
+ }
39
+
40
+ @GetMapping("/student/{netID}/editPage")
41
+ public String populateEditStudentPage(@PathVariable("netID") String netID, Model model) {
42
+ String sql = "SELECT * FROM student WHERE netID = ?";
43
+ Map<String, Object> student = jdbcTemplate.queryForMap(sql, netID);
44
+ model.addAttribute("student", student);
45
+ return "student/editStudents";
46
+ }
47
+
48
+ @GetMapping("/student/{netID}/characters")
49
+ public String showPage(@PathVariable("netID") String netID, Model model) {
50
+
51
+ String sql = "SELECT * FROM characters WHERE netID = ?";
52
+ List<Map<String, Object>> character = jdbcTemplate.queryForList(sql, netID);
53
+ model.addAttribute("roles", character);
54
+ return "characters/character";
55
+ }
56
+
57
+ /*-----------------------------------------
58
+ CHARACTER PAGES
59
+ -----------------------------------------*/
60
+ @GetMapping("/characters/loadpage")
61
+ public String charactersPage() {
62
+ return "characters/character";
63
+ }
64
+
65
+ @GetMapping("/characters/addpage")
66
+ public String addCharactersPage() {
67
+ return "characters/addCharacters";
68
+ }
69
+
70
+ /*----------------
71
+ ACTOR PAGES
72
+ ----------------*/
73
+
74
+ @GetMapping("/actors/loadpage")
75
+ public String actorsPage() {
76
+ return "actor/actors";
77
+ }
78
+
79
+ @GetMapping("/actor/add")
80
+ public String addActorPage() {
81
+ return "actor/addActors";
82
+ }
83
+
84
+ @GetMapping("/actor/editPage")
85
+ public String populateEditActorPage(@RequestParam("netID") String netID, Model model) {
86
+ String sql = """
87
+ SELECT
88
+ s.firstName AS firstName,
89
+ s.lastName AS lastName,
90
+ a.netID AS netID,
91
+ a.yearsActingExperience AS yearsActingExperience,
92
+ a.skinTone AS skinTone,
93
+ a.piercings AS piercings,
94
+ a.hairColor AS hairColor,
95
+ a.previousInjuries AS previousInjuries,
96
+ a.specialNotes AS specialNotes,
97
+ a.height AS height,
98
+ a.ringSize AS ringSize,
99
+ a.shoeSize AS shoeSize,
100
+ a.headCirc AS headCirc,
101
+ a.neckBase AS neckBase,
102
+ a.chest AS chest,
103
+ a.waist AS waist,
104
+ a.highHip AS highHip,
105
+ a.lowHip AS lowHip,
106
+ a.armseyeToArmseyeFront AS armseyeToArmseyeFront,
107
+ a.neckToWaistFront AS neckToWaistFront,
108
+ a.armseyeToArmseyeBack AS armseyeToArmseyeBack,
109
+ a.neckToWaistBack AS neckToWaistBack,
110
+ a.centerBackToWrist AS centerBackToWrist,
111
+ a.outsleeveToWrist AS outsleeveToWrist,
112
+ a.outseamBelowKnee AS outseamBelowKnee,
113
+ a.outseamToAnkle AS outseamToAnkle,
114
+ a.outseamToFloor AS outseamToFloor,
115
+ a.otherNotes AS otherNotes
116
+ FROM actor a
117
+ JOIN student s ON a.netID = s.netID
118
+ WHERE a.netID = ?
119
+ """;
120
+ Map<String, Object> actor = jdbcTemplate.queryForMap(sql, netID);
121
+ model.addAttribute("actor", actor);
122
+ return "actor/editActor";
123
+ }
124
+
125
+ /*-----------------------------------------
126
+ CREW PAGES
127
+ -----------------------------------------*/
128
+ @GetMapping("/crew/loadpage")
129
+ public String crewPage() {
130
+ return "crew/crew";
131
+ }
132
+
133
+ @GetMapping("/crew/add")
134
+ public String addCrewPage() {
135
+ return "crew/addCrew";
136
+ }
137
+
138
+ /*-----------------------------------------
139
+ SHOW PAGES
140
+ -----------------------------------------*/
141
+ @GetMapping("/show/loadpage")
142
+ public String showPage() {
143
+ return "shows/shows";
144
+ }
145
+
146
+ }
src/main/java/com/creighton_theater/theater_database/TheaterDatabaseApplication.java ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package com.creighton_theater.theater_database;
2
+
3
+ import org.springframework.boot.SpringApplication;
4
+ import org.springframework.boot.autoconfigure.SpringBootApplication;
5
+
6
+ @SpringBootApplication
7
+ public class TheaterDatabaseApplication {
8
+
9
+ public static void main(String[] args) {
10
+ SpringApplication.run(TheaterDatabaseApplication.class, args);
11
+ }
12
+
13
+ }
src/main/java/com/creighton_theater/theater_database/actorRestController.java ADDED
@@ -0,0 +1,182 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package com.creighton_theater.theater_database;
2
+
3
+ import java.util.List;
4
+ import java.util.Map;
5
+
6
+ import org.springframework.beans.factory.annotation.Autowired;
7
+ import org.springframework.http.HttpStatus;
8
+ import org.springframework.http.ResponseEntity;
9
+ import org.springframework.jdbc.core.JdbcTemplate;
10
+ import org.springframework.web.bind.annotation.GetMapping;
11
+ import org.springframework.web.bind.annotation.PostMapping;
12
+ import org.springframework.web.bind.annotation.RequestMapping;
13
+ import org.springframework.web.bind.annotation.RequestParam;
14
+ import org.springframework.web.bind.annotation.RestController;
15
+
16
+ @RestController
17
+ @RequestMapping("/actors")
18
+ public class actorRestController {
19
+ @Autowired
20
+ private JdbcTemplate jdbcTemplate;
21
+
22
+ @GetMapping("/getAll")
23
+ public List<Map<String, Object>> getAllActors() {
24
+ System.out.println("penis");
25
+ String sql = """
26
+ SELECT
27
+ s.firstName AS firstName,
28
+ s.lastName AS lastName,
29
+ a.netID AS netID,
30
+ a.yearsActingExperience AS yearsActingExperience,
31
+ a.skinTone AS skinTone,
32
+ a.piercings AS piercings,
33
+ a.hairColor AS hairColor,
34
+ a.previousInjuries AS previousInjuries,
35
+ a.specialNotes AS specialNotes,
36
+ a.height AS height,
37
+ a.ringSize AS ringSize,
38
+ a.shoeSize AS shoeSize,
39
+ a.headCirc AS headCirc,
40
+ a.neckBase AS neckBase,
41
+ a.chest AS chest,
42
+ a.waist AS waist,
43
+ a.highHip AS highHip,
44
+ a.lowHip AS lowHip,
45
+ a.armseyeToArmseyeFront AS armseyeToArmseyeFront,
46
+ a.neckToWaistFront AS neckToWaistFront,
47
+ a.armseyeToArmseyeBack AS armseyeToArmseyeBack,
48
+ a.neckToWaistBack AS neckToWaistBack,
49
+ a.centerBackToWrist AS centerBackToWrist,
50
+ a.outsleeveToWrist AS outsleeveToWrist,
51
+ a.outseamBelowKnee AS outseamBelowKnee,
52
+ a.outseamToAnkle AS outseamToAnkle,
53
+ a.outseamToFloor AS outseamToFloor,
54
+ a.otherNotes AS otherNotes
55
+ FROM actor a
56
+ JOIN student s ON a.netID = s.netID
57
+ """;
58
+ return jdbcTemplate.queryForList(sql);
59
+ }
60
+
61
+ @GetMapping("/filterBy")
62
+ public List<Map<String, Object>> filterBy(
63
+ @RequestParam String value) {
64
+
65
+ try {
66
+ String sql = "SELECT * FROM actor JOIN student ON actor.netID = student.netID WHERE actor.netID LIKE ?";
67
+
68
+ return jdbcTemplate.queryForList(sql, new Object[] { "%" + value + "%" });
69
+ } catch (Exception e) {
70
+ e.printStackTrace();
71
+ return null;
72
+ }
73
+ }
74
+
75
+ @PostMapping("/add")
76
+ public ResponseEntity<String> addActor(
77
+ String netID,
78
+ Integer yearsActingExperience,
79
+ String skinTone,
80
+ String piercings,
81
+ String hairColor,
82
+ String previousInjuries,
83
+ String specialNotes,
84
+ String height,
85
+ String ringSize,
86
+ String shoeSize,
87
+ String headCirc,
88
+ String neckBase,
89
+ String chest,
90
+ String waist,
91
+ String highHip,
92
+ String lowHip,
93
+ String armseyeToArmseyeFront,
94
+ String neckToWaistFront,
95
+ String armseyeToArmseyeBack,
96
+ String neckToWaistBack,
97
+ String centerBackToWrist,
98
+ String outsleeveToWrist,
99
+ String outseamBelowKnee,
100
+ String outseamToAnkle,
101
+ String outseamToFloor,
102
+ String otherNotes) {
103
+ String sql = """
104
+ INSERT INTO actor (
105
+ netID, yearsActingExperience, skinTone, piercings, hairColor, previousInjuries,
106
+ specialNotes, height, ringSize, shoeSize, headCirc,
107
+ neckBase, chest, waist, highHip, lowHip,
108
+ armseyeToArmseyeFront, neckToWaistFront, armseyeToArmseyeBack,
109
+ neckToWaistBack, centerBackToWrist, outsleeveToWrist,
110
+ outseamBelowKnee, outseamToAnkle, outseamToFloor,
111
+ otherNotes
112
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);
113
+ """;
114
+
115
+ try {
116
+ jdbcTemplate.update(sql, netID, yearsActingExperience, skinTone, piercings, hairColor, previousInjuries,
117
+ specialNotes, height, ringSize, shoeSize, headCirc,
118
+ neckBase, chest, waist, highHip, lowHip,
119
+ armseyeToArmseyeFront, neckToWaistFront, armseyeToArmseyeBack,
120
+ neckToWaistBack, centerBackToWrist, outsleeveToWrist,
121
+ outseamBelowKnee, outseamToAnkle, outseamToFloor,
122
+ otherNotes);
123
+ return ResponseEntity.ok("Actor added successfully");
124
+ } catch (Exception e) {
125
+ e.printStackTrace();
126
+ return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
127
+ .body("Error adding actor: " + e.getMessage());
128
+ }
129
+ }
130
+
131
+ @PostMapping("/edit")
132
+ public String editActor(
133
+ @RequestParam("netID") String netID,
134
+ @RequestParam(required = false) Integer yearsActingExperience,
135
+ @RequestParam(required = false) String skinTone,
136
+ @RequestParam(required = false) String piercings,
137
+ @RequestParam(required = false) String hairColor,
138
+ @RequestParam(required = false) String previousInjuries,
139
+ @RequestParam(required = false) String specialNotes,
140
+ @RequestParam(required = false) String height,
141
+ @RequestParam(required = false) String ringSize,
142
+ @RequestParam(required = false) String shoeSize,
143
+ @RequestParam(required = false) String headCirc,
144
+ @RequestParam(required = false) String neckBase,
145
+ @RequestParam(required = false) String chest,
146
+ @RequestParam(required = false) String waist,
147
+ @RequestParam(required = false) String highHip,
148
+ @RequestParam(required = false) String lowHip,
149
+ @RequestParam(required = false) String armseyeToArmseyeFront,
150
+ @RequestParam(required = false) String neckToWaistFront,
151
+ @RequestParam(required = false) String armseyeToArmseyeBack,
152
+ @RequestParam(required = false) String neckToWaistBack,
153
+ @RequestParam(required = false) String centerBackToWrist,
154
+ @RequestParam(required = false) String outsleeveToWrist,
155
+ @RequestParam(required = false) String outseamBelowKnee,
156
+ @RequestParam(required = false) String outseamToAnkle,
157
+ @RequestParam(required = false) String outseamToFloor,
158
+ @RequestParam(required = false) String otherNotes) {
159
+ String sql = """
160
+ UPDATE actor
161
+ SET yearsActingExperience = ?, skinTone = ?, piercings = ?, hairColor = ?,
162
+ previousInjuries = ?, specialNotes = ?, height = ?, ringSize = ?, shoeSize = ?,
163
+ headCirc = ?, neckBase = ?, chest = ?, waist = ?, highHip = ?, lowHip = ?,
164
+ armseyeToArmseyeFront = ?, neckToWaistFront = ?, armseyeToArmseyeBack = ?,
165
+ neckToWaistBack = ?, centerBackToWrist = ?, outsleeveToWrist = ?,
166
+ outseamBelowKnee = ?, outseamToAnkle = ?, outseamToFloor = ?, otherNotes = ?
167
+ WHERE netID = ?
168
+ """;
169
+
170
+ jdbcTemplate.update(sql,
171
+ yearsActingExperience, skinTone, piercings, hairColor,
172
+ previousInjuries, specialNotes, height, ringSize, shoeSize,
173
+ headCirc, neckBase, chest, waist, highHip, lowHip,
174
+ armseyeToArmseyeFront, neckToWaistFront, armseyeToArmseyeBack,
175
+ neckToWaistBack, centerBackToWrist, outsleeveToWrist,
176
+ outseamBelowKnee, outseamToAnkle, outseamToFloor, otherNotes,
177
+ netID);
178
+
179
+ return "OK";
180
+ }
181
+
182
+ }
src/main/java/com/creighton_theater/theater_database/characterRestController.java ADDED
@@ -0,0 +1,120 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package com.creighton_theater.theater_database;
2
+
3
+ import java.util.HashMap;
4
+ import java.util.List;
5
+ import java.util.Map;
6
+
7
+ import org.springframework.beans.factory.annotation.Autowired;
8
+ import org.springframework.dao.DataAccessException;
9
+ import org.springframework.dao.DataIntegrityViolationException;
10
+ import org.springframework.http.HttpStatus;
11
+ import org.springframework.http.ResponseEntity;
12
+ import org.springframework.jdbc.core.JdbcTemplate;
13
+ import org.springframework.web.bind.annotation.GetMapping;
14
+ import org.springframework.web.bind.annotation.PostMapping;
15
+ import org.springframework.web.bind.annotation.RequestMapping;
16
+ import org.springframework.web.bind.annotation.RequestParam;
17
+ import org.springframework.web.bind.annotation.RestController;
18
+
19
+ @RestController
20
+ @RequestMapping("/characters")
21
+ public class characterRestController {
22
+ @Autowired
23
+ private JdbcTemplate jdbcTemplate;
24
+
25
+ @GetMapping("/getAll")
26
+ public List<Map<String, Object>> getAllCharacters() {
27
+ String sql = """
28
+ SELECT
29
+ s.firstName AS firstName,
30
+ s.lastName AS lastName,
31
+ c.characterName AS characterName,
32
+ c.netID AS netID,
33
+ c.showID AS showID,
34
+ sh.showName AS showName,
35
+ sh.yearSemester AS showSemester
36
+ FROM characters c
37
+ JOIN student s ON c.netID = s.netID
38
+ JOIN shows sh ON c.showID = sh.showID
39
+ """;
40
+ return jdbcTemplate.queryForList(sql);
41
+ }
42
+
43
+ @GetMapping("/filterBy")
44
+ public List<Map<String, Object>> filterBy(
45
+ @RequestParam String column,
46
+ @RequestParam String value,
47
+ @RequestParam String page) {
48
+
49
+ try {
50
+ String sql = """
51
+ SELECT
52
+ s.firstName AS firstName,
53
+ s.lastName AS lastName,
54
+ c.characterName AS characterName,
55
+ c.netID AS netID,
56
+ c.showID AS showID,
57
+ sh.showName AS showName,
58
+ sh.yearSemester AS showSemester
59
+ FROM characters c
60
+ JOIN student s ON c.netID = s.netID
61
+ JOIN shows sh ON c.showID = sh.showID
62
+ WHERE """ + " " + page + "." + column + " LIKE ?";
63
+
64
+ return jdbcTemplate.queryForList(sql, new Object[] { "%" + value + "%" });
65
+
66
+ } catch (Exception e) {
67
+ e.printStackTrace();
68
+ return List.of();
69
+ }
70
+ }
71
+
72
+ @PostMapping("/edit")
73
+ public String editCharacter(
74
+ @RequestParam("NewCharacterName") String newCharacterName,
75
+ @RequestParam("netID") String netID,
76
+ @RequestParam("OldcharacterName") String oldCharacterName) {
77
+
78
+ String sql = "UPDATE characters SET characterName = ?, netID = ? WHERE characterName = ?;";
79
+ jdbcTemplate.update(sql, newCharacterName, netID, oldCharacterName);
80
+
81
+ return "OK";
82
+ }
83
+
84
+ @PostMapping("/add")
85
+ public ResponseEntity<Map<String, String>> addCharacter(
86
+ @RequestParam("characterName") String characterName,
87
+ @RequestParam("netID") String netID,
88
+ @RequestParam("showID") String showID) {
89
+ Map<String, String> response = new HashMap<>();
90
+ try {
91
+ String sql = "INSERT INTO characters (characterName, netID, showID) VALUES (?, ?, ?)";
92
+ jdbcTemplate.update(sql, characterName, netID, showID);
93
+
94
+ response.put("status", "success");
95
+ response.put("message", "Character added successfully!");
96
+ return ResponseEntity.ok(response);
97
+
98
+ } catch (DataIntegrityViolationException e) {
99
+ String message = e.getRootCause() != null ? e.getRootCause().getMessage() : e.getMessage();
100
+
101
+ // Check if the message indicates a foreign key violation
102
+ if (message != null && message.toLowerCase().contains("foreign key")) {
103
+ response.put("status", "error");
104
+ response.put("message", "Cannot add character: referenced netID or showID does not exist.");
105
+ } else {
106
+ response.put("status", "error");
107
+ response.put("message", message);
108
+ }
109
+
110
+ return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(response);
111
+
112
+ } catch (DataAccessException e) {
113
+ // Fallback for other database exceptions
114
+ response.put("status", "error");
115
+ response.put("message", e.getRootCause() != null ? e.getRootCause().getMessage() : e.getMessage());
116
+ return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(response);
117
+ }
118
+
119
+ }
120
+ }
src/main/java/com/creighton_theater/theater_database/crewRestController.java ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package com.creighton_theater.theater_database;
2
+
3
+ import java.util.List;
4
+ import java.util.Map;
5
+
6
+ import org.springframework.beans.factory.annotation.Autowired;
7
+ import org.springframework.dao.DataAccessException;
8
+ import org.springframework.http.HttpStatus;
9
+ import org.springframework.http.ResponseEntity;
10
+ import org.springframework.jdbc.core.JdbcTemplate;
11
+ import org.springframework.web.bind.annotation.GetMapping;
12
+ import org.springframework.web.bind.annotation.PostMapping;
13
+ import org.springframework.web.bind.annotation.RequestMapping;
14
+ import org.springframework.web.bind.annotation.RequestParam;
15
+ import org.springframework.web.bind.annotation.RestController;
16
+
17
+ @RestController
18
+ @RequestMapping("/crew")
19
+ public class crewRestController {
20
+ @Autowired
21
+ private JdbcTemplate jdbcTemplate;
22
+
23
+ @GetMapping("/getAll")
24
+ public List<Map<String, Object>> getAllCrew() {
25
+ System.out.println("penis2");
26
+ String sql = """
27
+ SELECT
28
+ c.crewID AS crewID,
29
+ c.firstName AS firstName,
30
+ c.lastName AS lastName,
31
+ CASE WHEN c.wigTrained = 1 THEN 'Yes' ELSE 'No' END AS wigTrained,
32
+ CASE WHEN c.makeupTrained = 1 THEN 'Yes' ELSE 'No' END AS makeupTrained,
33
+ CASE WHEN c.musicReading = 1 THEN 'Yes' ELSE 'No' END AS musicReading,
34
+ c.lighting AS lighting,
35
+ c.sound AS sound,
36
+ c.specialty AS specialty,
37
+ c.notes AS notes
38
+ FROM crew c
39
+ """;
40
+ return jdbcTemplate.queryForList(sql);
41
+ }
42
+
43
+ @GetMapping("/filterBy")
44
+ public List<Map<String, Object>> filterBy(
45
+ @RequestParam String value) {
46
+
47
+ try {
48
+ String sql = "SELECT * FROM crew WHERE crew.crewID LIKE ?";
49
+
50
+ return jdbcTemplate.queryForList(sql, new Object[] { "%" + value + "%" });
51
+ } catch (Exception e) {
52
+ e.printStackTrace();
53
+ return null;
54
+ }
55
+ }
56
+
57
+ @PostMapping("/addCrew")
58
+ public ResponseEntity<String> addCrew(
59
+ String crewID,
60
+ String firstName,
61
+ String lastName,
62
+ Integer wigTrained,
63
+ Integer makeupTrained,
64
+ Integer musicReading,
65
+ String lighting,
66
+ String sound,
67
+ String specialty,
68
+ String notes) {
69
+ String sql = "INSERT INTO crew (crewID, firstName, lastName, wigTrained, makeupTrained, musicReading, lighting, sound, specialty, notes) "
70
+ +
71
+ "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
72
+
73
+ try {
74
+ jdbcTemplate.update(sql,
75
+ crewID,
76
+ firstName,
77
+ lastName,
78
+ wigTrained != null ? wigTrained : 0,
79
+ makeupTrained != null ? makeupTrained : 0,
80
+ musicReading != null ? musicReading : 0,
81
+ lighting,
82
+ sound,
83
+ specialty,
84
+ notes);
85
+ return ResponseEntity.ok("Crew member added successfully!");
86
+ } catch (DataAccessException e) {
87
+ return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
88
+ .body("Error adding crew member: " + e.getMessage());
89
+ }
90
+ }
91
+
92
+ }
src/main/java/com/creighton_theater/theater_database/showRestController.java ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package com.creighton_theater.theater_database;
2
+
3
+ import java.util.List;
4
+ import java.util.Map;
5
+
6
+ import org.springframework.beans.factory.annotation.Autowired;
7
+ import org.springframework.jdbc.core.JdbcTemplate;
8
+ import org.springframework.web.bind.annotation.GetMapping;
9
+ import org.springframework.web.bind.annotation.RequestMapping;
10
+ import org.springframework.web.bind.annotation.RequestParam;
11
+ import org.springframework.web.bind.annotation.RestController;
12
+
13
+ @RestController
14
+ @RequestMapping("/shows")
15
+ public class showRestController {
16
+ @Autowired
17
+ private JdbcTemplate jdbcTemplate;
18
+
19
+ @GetMapping("/getAll")
20
+ public List<Map<String, Object>> getAllShows() {
21
+ String sql = """
22
+ SELECT
23
+ s.showID as showID,
24
+ s.showName as showName,
25
+ s.yearSemester as yearSemester,
26
+ s.Director as director,
27
+ s.genre as genre,
28
+ s.playWright as playWright
29
+ FROM shows s
30
+ """;
31
+ return jdbcTemplate.queryForList(sql);
32
+ }
33
+
34
+ @GetMapping("/getShowIDName")
35
+ public List<Map<String, Object>> getShowIDName(@RequestParam String searchBy, @RequestParam String searchValue) {
36
+ try {
37
+ String sql = "SELECT showName, yearSemester, showID FROM shows WHERE " + searchBy + " LIKE ?";
38
+ return jdbcTemplate.queryForList(sql, new Object[] { "%" + searchValue + "%" });
39
+ } catch (Exception e) {
40
+ return List.of();
41
+ }
42
+ }
43
+ }
src/main/java/com/creighton_theater/theater_database/studentRestController.java ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package com.creighton_theater.theater_database;
2
+
3
+ import java.util.List;
4
+ import java.util.Map;
5
+
6
+ import org.springframework.beans.factory.annotation.Autowired;
7
+ import org.springframework.jdbc.core.JdbcTemplate;
8
+ import org.springframework.web.bind.annotation.GetMapping;
9
+ import org.springframework.web.bind.annotation.PathVariable;
10
+ import org.springframework.web.bind.annotation.PostMapping;
11
+ import org.springframework.web.bind.annotation.RequestMapping;
12
+ import org.springframework.web.bind.annotation.RequestParam;
13
+ import org.springframework.web.bind.annotation.RestController;
14
+
15
+ @RestController
16
+ @RequestMapping("/student")
17
+ public class studentRestController {
18
+ @Autowired
19
+ private JdbcTemplate jdbcTemplate;
20
+
21
+ // retrieves all students from database
22
+ @GetMapping("/getAll")
23
+ public List<Map<String, Object>> getAllStudents() {
24
+ String sql = "SELECT * FROM student";
25
+ return jdbcTemplate.queryForList(sql);
26
+ }
27
+
28
+ @GetMapping("/filterBy")
29
+ public List<Map<String, Object>> filterBy(String column, String value) {
30
+ try {
31
+ String sql = "SELECT * FROM student WHERE " + column + " LIKE ?";
32
+ return jdbcTemplate.queryForList(sql, new Object[] { "%" + value + "%" });
33
+ } catch (Exception e) {
34
+ return null;
35
+ }
36
+ }
37
+
38
+ @PostMapping("{netID}/edit")
39
+ public String editStudent(
40
+ @PathVariable String netID, // old netID from URL
41
+ @RequestParam String newNetID,
42
+ @RequestParam String firstName,
43
+ @RequestParam String lastName,
44
+ @RequestParam String gradeLevel,
45
+ @RequestParam String pronouns,
46
+ @RequestParam String specialNotes,
47
+ @RequestParam String email,
48
+ @RequestParam String allergies_sensitivities) {
49
+
50
+ String sql = """
51
+ UPDATE student
52
+ SET netID = ?, firstName = ?, lastName = ?, gradeLevel = ?, pronouns = ?,
53
+ specialNotes = ?, email = ?, allergies_sensitivities = ?
54
+ WHERE netID = ?
55
+ """;
56
+
57
+ jdbcTemplate.update(sql,
58
+ newNetID, firstName, lastName, gradeLevel, pronouns,
59
+ specialNotes, email, allergies_sensitivities,
60
+ netID // old
61
+ );
62
+
63
+ return "OK";
64
+ }
65
+
66
+ }
src/main/resources/application.properties ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ spring.application.name=theater_database
2
+
3
+ # H2 Database Configuration for Hugging Face Spaces
4
+ spring.datasource.url=jdbc:h2:mem:creightontheater
5
+ spring.datasource.driver-class-name=org.h2.Driver
6
+ spring.datasource.username=sa
7
+ spring.datasource.password=
8
+
9
+ # H2 Console (optional - for debugging)
10
+ spring.h2.console.enabled=true
11
+ spring.h2.console.path=/h2-console
12
+
13
+ spring.jpa.show-sql=true
14
+ spring.jpa.generate-ddl=true
15
+ spring.jpa.hibernate.ddl-auto=create-drop
16
+ spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect
17
+ spring.sql.init.mode=always
18
+
19
+ # Server port for Hugging Face Spaces
20
+ server.port=7860
21
+
src/main/resources/schema.sql ADDED
@@ -0,0 +1,153 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ -- -----------------------------------------------------
2
+ -- Table `student`
3
+ -- -----------------------------------------------------
4
+ CREATE TABLE IF NOT EXISTS student (
5
+ netID VARCHAR(8) NOT NULL,
6
+ firstName VARCHAR(45) NOT NULL,
7
+ lastName VARCHAR(45) NOT NULL,
8
+ gradeLevel VARCHAR(45) NOT NULL,
9
+ pronouns VARCHAR(45) NOT NULL,
10
+ specialNotes VARCHAR(100) NOT NULL,
11
+ email VARCHAR(45) DEFAULT NULL,
12
+ allergies_sensitivities VARCHAR(45) DEFAULT NULL,
13
+ PRIMARY KEY (netID)
14
+ ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb3;
15
+ -- -----------------------------------------------------
16
+ -- Table `actor`
17
+ -- -----------------------------------------------------
18
+ CREATE TABLE IF NOT EXISTS actor (
19
+ netID VARCHAR(8) NOT NULL,
20
+ yearsActingExperience INT DEFAULT NULL,
21
+ skinTone VARCHAR(45) DEFAULT NULL,
22
+ piercings VARCHAR(50) DEFAULT NULL,
23
+ hairColor VARCHAR(45) DEFAULT NULL,
24
+ previousInjuries VARCHAR(90) DEFAULT NULL,
25
+ specialNotes VARCHAR(200) DEFAULT NULL,
26
+ height VARCHAR(45) DEFAULT NULL,
27
+ ringSize VARCHAR(45) DEFAULT NULL,
28
+ shoeSize VARCHAR(45) DEFAULT NULL,
29
+ headCirc DOUBLE DEFAULT NULL,
30
+ neckBase DOUBLE DEFAULT NULL,
31
+ chest DOUBLE DEFAULT NULL,
32
+ waist DOUBLE DEFAULT NULL,
33
+ highHip DOUBLE DEFAULT NULL,
34
+ lowHip DOUBLE DEFAULT NULL,
35
+ armseyeToArmseyeFront DOUBLE DEFAULT NULL,
36
+ neckToWaistFront DOUBLE DEFAULT NULL,
37
+ armseyeToArmseyeBack DOUBLE DEFAULT NULL,
38
+ neckToWaistBack DOUBLE DEFAULT NULL,
39
+ centerBackToWrist DOUBLE DEFAULT NULL,
40
+ outsleeveToWrist DOUBLE DEFAULT NULL,
41
+ outseamBelowKnee DOUBLE DEFAULT NULL,
42
+ outseamToAnkle DOUBLE DEFAULT NULL,
43
+ outseamToFloor DOUBLE DEFAULT NULL,
44
+ otherNotes VARCHAR(100) DEFAULT NULL,
45
+ photo BLOB DEFAULT NULL,
46
+ PRIMARY KEY (netID),
47
+ INDEX fk_ACTOR_STUDENT1_idx (netID ASC),
48
+ CONSTRAINT fk_ACTOR_STUDENT1 FOREIGN KEY (netID) REFERENCES student(netID)
49
+ ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb3;
50
+ -- -----------------------------------------------------
51
+ -- Table `shows`
52
+ -- -----------------------------------------------------
53
+ CREATE TABLE IF NOT EXISTS shows (
54
+ showID INT NOT NULL AUTO_INCREMENT,
55
+ showName VARCHAR(45) DEFAULT NULL,
56
+ yearSemester VARCHAR(45) DEFAULT NULL,
57
+ genre VARCHAR(45) DEFAULT NULL,
58
+ playWright VARCHAR(45) DEFAULT NULL,
59
+ PRIMARY KEY (showID)
60
+ ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb3;
61
+ -- -----------------------------------------------------
62
+ -- Table `characters`
63
+ -- -----------------------------------------------------
64
+ CREATE TABLE IF NOT EXISTS characters (
65
+ showID INT NOT NULL,
66
+ characterName VARCHAR(45) NOT NULL,
67
+ netID VARCHAR(8) NOT NULL,
68
+ PRIMARY KEY (showID, characterName, netID),
69
+ INDEX fk_CHARACTERS_ACTOR1_idx (netID ASC),
70
+ CONSTRAINT fk_CHARACTERS_ACTOR1 FOREIGN KEY (netID) REFERENCES actor(netID),
71
+ CONSTRAINT fk_CHARACTERS_SHOW1 FOREIGN KEY (showID) REFERENCES shows(showID)
72
+ ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb3;
73
+ -- -----------------------------------------------------
74
+ -- Table `crew`
75
+ -- -----------------------------------------------------
76
+ CREATE TABLE IF NOT EXISTS crew (
77
+ crewID VARCHAR(8) NOT NULL,
78
+ wigTrained BINARY(1) DEFAULT NULL,
79
+ makeupTrained BINARY(1) DEFAULT NULL,
80
+ musicReading BINARY(1) DEFAULT NULL,
81
+ lighting VARCHAR(90) DEFAULT NULL,
82
+ sound VARCHAR(90) DEFAULT NULL,
83
+ studentNonStudent BINARY(1) DEFAULT NULL,
84
+ contractOrHired BINARY(1) DEFAULT NULL,
85
+ specialty VARCHAR(45) DEFAULT NULL,
86
+ notes VARCHAR(45) DEFAULT NULL,
87
+ PRIMARY KEY (crewID),
88
+ INDEX fk_CREW_STUDENT_idx (crewID ASC),
89
+ CONSTRAINT fk_CREW_STUDENT FOREIGN KEY (crewID) REFERENCES student(netID)
90
+ ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb3;
91
+ -- -----------------------------------------------------
92
+ -- Table `scene`
93
+ -- -----------------------------------------------------
94
+ CREATE TABLE IF NOT EXISTS scene (
95
+ sceneName VARCHAR(45) NOT NULL,
96
+ showID INT NOT NULL,
97
+ act INT DEFAULT NULL,
98
+ locationSet VARCHAR(45) DEFAULT NULL,
99
+ song VARCHAR(45) DEFAULT NULL,
100
+ bookScriptPages VARCHAR(45) DEFAULT NULL,
101
+ crewNetID VARCHAR(8) NOT NULL,
102
+ PRIMARY KEY (sceneName),
103
+ INDEX fk_SCENE_SHOW1_idx (showID ASC),
104
+ CONSTRAINT fk_SCENE_SHOW1 FOREIGN KEY (showID) REFERENCES shows(showID)
105
+ ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb3;
106
+ -- -----------------------------------------------------
107
+ -- Table `character_in_scene`
108
+ -- -----------------------------------------------------
109
+ CREATE TABLE IF NOT EXISTS character_in_scene (
110
+ sceneName VARCHAR(45) NOT NULL,
111
+ costumeChange VARCHAR(45) DEFAULT NULL,
112
+ costumeWorn VARCHAR(45) DEFAULT NULL,
113
+ characterLocation VARCHAR(45) DEFAULT NULL,
114
+ changeLocation VARCHAR(45) DEFAULT NULL,
115
+ changeLengthOfTime VARCHAR(45) DEFAULT NULL,
116
+ additionalNotes VARCHAR(45) DEFAULT NULL,
117
+ crewID VARCHAR(8) DEFAULT NULL,
118
+ showID INT NOT NULL,
119
+ characterName VARCHAR(45) NOT NULL,
120
+ netID VARCHAR(8) NOT NULL,
121
+ PRIMARY KEY (sceneName, showID, characterName, netID),
122
+ INDEX fk_CHARACTERS_has_SCENE_SCENE1_idx (sceneName ASC),
123
+ INDEX fk_CHARACTER_IN_SCENE_CREW1_idx (crewID ASC),
124
+ INDEX fk_CHARACTER_IN_SCENE_CHARACTERS1_idx (showID ASC, characterName ASC, netID ASC),
125
+ CONSTRAINT fk_CHARACTER_IN_SCENE_CHARACTERS1 FOREIGN KEY (showID, characterName, netID) REFERENCES characters(showID, characterName, netID),
126
+ CONSTRAINT fk_CHARACTER_IN_SCENE_CREW1 FOREIGN KEY (crewID) REFERENCES crew(crewID),
127
+ CONSTRAINT fk_CHARACTERS_has_SCENE_SCENE1 FOREIGN KEY (sceneName) REFERENCES scene(sceneName)
128
+ ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb3;
129
+ -- -----------------------------------------------------
130
+ -- Table `crew_in_show`
131
+ -- -----------------------------------------------------
132
+ CREATE TABLE IF NOT EXISTS crew_in_show (
133
+ showID INT NOT NULL,
134
+ roles VARCHAR(45) DEFAULT NULL,
135
+ crewID VARCHAR(8) NOT NULL,
136
+ PRIMARY KEY (showID),
137
+ INDEX fk_STUDENT_has_SHOW_SHOW1_idx (showID ASC),
138
+ INDEX fk_CREW_IN_SHOW_CREW1_idx (crewID ASC),
139
+ CONSTRAINT fk_CREW_IN_SHOW_CREW1 FOREIGN KEY (crewID) REFERENCES crew(crewID),
140
+ CONSTRAINT fk_STUDENT_has_SHOW_SHOW1 FOREIGN KEY (showID) REFERENCES shows(showID)
141
+ ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb3;
142
+ -- -----------------------------------------------------
143
+ -- Table `previous_roles`
144
+ -- -----------------------------------------------------
145
+ CREATE TABLE IF NOT EXISTS previous_roles (
146
+ netID VARCHAR(8) NOT NULL,
147
+ showID INT NOT NULL,
148
+ PRIMARY KEY (netID),
149
+ INDEX fk_PREVIOUS_ROLES_STUDENT1_idx (netID ASC),
150
+ INDEX fk_PREVIOUS_ROLES_SHOW1_idx (showID ASC),
151
+ CONSTRAINT fk_PREVIOUS_ROLES_SHOW1 FOREIGN KEY (showID) REFERENCES shows(showID),
152
+ CONSTRAINT fk_PREVIOUS_ROLES_STUDENT1 FOREIGN KEY (netID) REFERENCES student(netID)
153
+ ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb3;
src/main/resources/static/actorScript.js ADDED
@@ -0,0 +1,233 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ function loadActors() {
2
+ const urlParams = new URLSearchParams(window.location.search);
3
+ const netID = urlParams.get("netID");
4
+
5
+ if (netID) {
6
+ document.getElementById("filter-input").value = netID;
7
+ processFilter();
8
+ } else {
9
+ fetch("/actors/getAll")
10
+ .then((response) => response.json())
11
+ .then((data) => {
12
+ const tableBody = document.getElementById("actor-table-body");
13
+ tableBody.innerHTML = "";
14
+
15
+ data.forEach((actor) => {
16
+ const row = document.createElement("tr");
17
+ row.innerHTML = `
18
+ <td>
19
+ <select class="netid-select"
20
+ onchange="handleNetIDDropdownActor(this.value, '${actor.netID}')">
21
+ <option value = "" selected>${actor.netID}</option>
22
+ <option value = "edit">Edit Actor</option>
23
+ </td>
24
+ <td class="sticky">${actor.firstName} ${actor.lastName}</td>
25
+ <td>${actor.yearsActingExperience}</td>
26
+ <td>${actor.skinTone}</td>
27
+ <td>${actor.piercings}</td>
28
+ <td>${actor.hairColor}</td>
29
+ <td>${actor.previousInjuries}</td>
30
+ <td>${actor.specialNotes}</td>
31
+ <td>${actor.height}</td>
32
+ <td>${actor.ringSize}</td>
33
+ <td>${actor.shoeSize}</td>
34
+ <td>${actor.headCirc}</td>
35
+ <td>${actor.neckBase}</td>
36
+ <td>${actor.chest}</td>
37
+ <td>${actor.waist}</td>
38
+ <td>${actor.highHip}</td>
39
+ <td>${actor.lowHip}</td>
40
+ <td>${actor.armseyeToArmseyeFront}</td>
41
+ <td>${actor.neckToWaistFront}</td>
42
+ <td>${actor.armseyeToArmseyeBack}</td>
43
+ <td>${actor.neckToWaistBack}</td>
44
+ <td>${actor.centerBackToWrist}</td>
45
+ <td>${actor.outsleeveToWrist}</td>
46
+ <td>${actor.outseamBelowKnee}</td>
47
+ <td>${actor.outseamToAnkle}</td>
48
+ <td>${actor.outseamToFloor}</td>
49
+ <td>${actor.otherNotes}</td>
50
+ `;
51
+
52
+ tableBody.appendChild(row);
53
+ });
54
+ })
55
+ .catch((error) => console.error("Error fetching actor data:", error));
56
+ }
57
+ }
58
+
59
+ function processFilter() {
60
+ const filterValue = document.getElementById("filter-input").value;
61
+
62
+ fetch(`/actors/filterBy?value=${filterValue}`)
63
+ .then((res) => res.json())
64
+ .then((data) => {
65
+ const tableBody = document.getElementById(`actor-table-body`);
66
+ tableBody.innerHTML = "";
67
+
68
+ data.forEach((actor) => {
69
+ const row = document.createElement("tr");
70
+ row.innerHTML = `
71
+ <td class="sticky">
72
+ <a href="/student/loadpage?netID=${actor.netID}">
73
+ ${actor.netID}
74
+ </a>
75
+ </td>
76
+ <td>${actor.yearsActingExperience}</td>
77
+ <td>${actor.skinTone}</td>
78
+ <td>${actor.piercings}</td>
79
+ <td>${actor.hairColor}</td>
80
+ <td>${actor.previousInjuries}</td>
81
+ <td>${actor.specialNotes}</td>
82
+ <td>${actor.height}</td>
83
+ <td>${actor.ringSize}</td>
84
+ <td>${actor.shoeSize}</td>
85
+ <td>${actor.headCirc}</td>
86
+ <td>${actor.neckBase}</td>
87
+ <td>${actor.chest}</td>
88
+ <td>${actor.waist}</td>
89
+ <td>${actor.highHip}</td>
90
+ <td>${actor.lowHip}</td>
91
+ <td>${actor.armseyeToArmseyeFront}</td>
92
+ <td>${actor.neckToWaistFront}</td>
93
+ <td>${actor.armseyeToArmseyeBack}</td>
94
+ <td>${actor.neckToWaistBack}</td>
95
+ <td>${actor.centerBackToWrist}</td>
96
+ <td>${actor.outsleeveToWrist}</td>
97
+ <td>${actor.outseamBelowKnee}</td>
98
+ <td>${actor.outseamToAnkle}</td>
99
+ <td>${actor.outseamToFloor}</td>
100
+ <td>${actor.otherNotes}</td>
101
+ `;
102
+ tableBody.appendChild(row);
103
+ });
104
+ });
105
+ }
106
+
107
+ function appendIfNotEmpty(formData, key, elementId) {
108
+ const val = document.getElementById(elementId).value;
109
+ if (val !== "") formData.append(key, val);
110
+ }
111
+
112
+ async function addActor() {
113
+ const formData = new URLSearchParams();
114
+
115
+ appendIfNotEmpty(formData, "netID", "netIDInput");
116
+ appendIfNotEmpty(formData, "skinTone", "skinTone");
117
+ appendIfNotEmpty(formData, "piercings", "piercings");
118
+ appendIfNotEmpty(formData, "hairColor", "hairColor");
119
+ appendIfNotEmpty(formData, "previousInjuries", "previousInjuries");
120
+ appendIfNotEmpty(formData, "specialNotes", "specialNotes");
121
+ appendIfNotEmpty(formData, "height", "height");
122
+ appendIfNotEmpty(formData, "ringSize", "ringSize");
123
+ appendIfNotEmpty(formData, "shoeSize", "shoeSize");
124
+ appendIfNotEmpty(formData, "headCirc", "headCirc");
125
+ appendIfNotEmpty(formData, "neckBase", "neckBase");
126
+ appendIfNotEmpty(formData, "chest", "chest");
127
+ appendIfNotEmpty(formData, "waist", "waist");
128
+ appendIfNotEmpty(formData, "highHip", "highHip");
129
+ appendIfNotEmpty(formData, "lowHip", "lowHip");
130
+ appendIfNotEmpty(formData, "armseyeToArmseyeFront", "armseyeToArmseyeFront");
131
+ appendIfNotEmpty(formData, "neckToWaistFront", "neckToWaistFront");
132
+ appendIfNotEmpty(formData, "armseyeToArmseyeBack", "armseyeToArmseyeBack");
133
+ appendIfNotEmpty(formData, "neckToWaistBack", "neckToWaistBack");
134
+ appendIfNotEmpty(formData, "centerBackToWrist", "centerBackToWrist");
135
+ appendIfNotEmpty(formData, "outsleeveToWrist", "outsleeveToWrist");
136
+ appendIfNotEmpty(formData, "outseamBelowKnee", "outseamBelowKnee");
137
+ appendIfNotEmpty(formData, "outseamToAnkle", "outseamToAnkle");
138
+ appendIfNotEmpty(formData, "outseamToFloor", "outseamToFloor");
139
+ appendIfNotEmpty(formData, "otherNotes", "otherNotes");
140
+
141
+ const response = await fetch("/actors/add", {
142
+ method: "POST",
143
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
144
+ body: formData.toString(),
145
+ });
146
+
147
+ const text = await response.text();
148
+
149
+ if (response.ok) {
150
+ alert(text); // "Actor added successfully"
151
+ document.getElementById("add-actor-form").reset();
152
+ window.location.href = "/actors/loadpage";
153
+ } else {
154
+ alert("Error adding actor: " + text); // now you’ll see the actual error
155
+ }
156
+
157
+ if (response.ok) {
158
+ alert("Actor added successfully!");
159
+ document.getElementById("add-actor-form").reset();
160
+ window.location.href = "/actors/loadpage";
161
+ } else {
162
+ alert("Error adding actor.");
163
+ }
164
+ }
165
+
166
+ async function editActor(netID) {
167
+ const formData = new URLSearchParams();
168
+
169
+ // Integer field
170
+ const years = document.getElementById("yearsActingExperience").value.trim();
171
+ formData.append(
172
+ "yearsActingExperience",
173
+ years === "" ? null : parseInt(years)
174
+ );
175
+
176
+ // String fields
177
+ formData.append("skinTone", document.getElementById("skinTone").value);
178
+ formData.append("piercings", document.getElementById("piercings").value);
179
+ formData.append("hairColor", document.getElementById("hairColor").value);
180
+ formData.append(
181
+ "previousInjuries",
182
+ document.getElementById("previousInjuries").value
183
+ );
184
+ formData.append(
185
+ "specialNotes",
186
+ document.getElementById("specialNotes").value
187
+ );
188
+ formData.append("height", document.getElementById("height").value);
189
+ formData.append("ringSize", document.getElementById("ringSize").value);
190
+ formData.append("shoeSize", document.getElementById("shoeSize").value);
191
+ formData.append("headCirc", headCirc);
192
+ console.log(typeof headCirc + "balls");
193
+ formData.append("neckBase", neckBase);
194
+ formData.append("chest", chest);
195
+ formData.append("waist", waist);
196
+ formData.append("highHip", highHip);
197
+ formData.append("lowHip", lowHip);
198
+ formData.append("armseyeToArmseyeFront", armseyeToArmseyeFront);
199
+ formData.append("neckToWaistFront", neckToWaistFront);
200
+ formData.append("armseyeToArmseyeBack", armseyeToArmseyeBack);
201
+ formData.append("neckToWaistBack", neckToWaistBack);
202
+ formData.append("centerBackToWrist", centerBackToWrist);
203
+ formData.append("outsleeveToWrist", outsleeveToWrist);
204
+ formData.append("outseamBelowKnee", outseamBelowKnee);
205
+ formData.append("outseamToAnkle", outseamToAnkle);
206
+ formData.append("outseamToFloor", outseamToFloor);
207
+ formData.append("otherNotes", document.getElementById("otherNotes").value);
208
+
209
+ const response = await fetch(
210
+ `/actors/edit?netID=${encodeURIComponent(netID)}`,
211
+ {
212
+ method: "POST",
213
+ body: formData,
214
+ }
215
+ );
216
+
217
+ if (response.ok) {
218
+ alert("Actor edited successfully!");
219
+ window.location.href = "/actors/loadpage";
220
+ } else {
221
+ const text = await response.text();
222
+ alert("Error editing actor: " + text);
223
+ }
224
+ }
225
+
226
+ function handleNetIDDropdownActor(selectedValue, netID) {
227
+ if (!selectedValue) {
228
+ return;
229
+ }
230
+ if (selectedValue === "edit") {
231
+ window.location.href = `/actor/editPage?netID=${netID}`;
232
+ }
233
+ }
src/main/resources/static/characterScript.js ADDED
@@ -0,0 +1,156 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ function loadCharacters() {
2
+ const urlParams = new URLSearchParams(window.location.search);
3
+ const netID = urlParams.get("netID");
4
+
5
+ if (netID) {
6
+ document.getElementById("filter-column").value = "netID,c";
7
+ document.getElementById("filter-input").value = netID;
8
+ processFilter();
9
+ } else {
10
+ fetch(`/characters/getAll`)
11
+ .then((response) => response.json())
12
+ .then((data) => {
13
+ const tableBody = document.getElementById("character-table-body");
14
+ tableBody.innerHTML = "";
15
+
16
+ data.forEach((character) => {
17
+ const row = document.createElement("tr");
18
+ row.innerHTML = `<td>
19
+ <select class="netid-select"
20
+ onchange="handleCharacterDropdown(this.value, '${character.characterName}')" id = "dropdown">
21
+ <option value="" selected>
22
+ ${character.characterName}
23
+ </option>
24
+ <option value="delete">Delete Character</option>
25
+ </select>
26
+ </td>
27
+ <td>${character.showName}</td>
28
+ <td>${character.showSemester}</td>
29
+ <td>${character.firstName} ${character.lastName}</td>
30
+ <td>${character.netID}</td>
31
+ <td>${character.showID}</td>`;
32
+ tableBody.appendChild(row);
33
+ });
34
+ })
35
+ .catch((error) => console.error("Error fetching character data:", error));
36
+ }
37
+ }
38
+
39
+ function handleCharacterDropdown(selectedValue, characterName) {
40
+ if (selectedValue === "") {
41
+ return;
42
+ }
43
+ if (selectedValue === "delete") {
44
+ window.location.href = `/characters/delete?characterName=${characterName}`;
45
+ }
46
+ }
47
+
48
+ //this function processes the filter request and updates the table accordingly
49
+ function processFilter() {
50
+ const filterBy = document.getElementById("filter-input").value;
51
+ const valueAndPage = splitValue(
52
+ document.getElementById("filter-column").value
53
+ );
54
+ const filterValue = valueAndPage[0];
55
+ const pageSearch = valueAndPage[1];
56
+ fetch(
57
+ `/characters/filterBy?column=${filterValue}&value=${filterBy}&page=${pageSearch}`
58
+ )
59
+ .then((res) => res.json())
60
+ .then((data) => {
61
+ const tableBody = document.getElementById(`character-table-body`);
62
+ tableBody.innerHTML = "";
63
+ data.forEach((character) => {
64
+ const row = document.createElement("tr");
65
+ row.innerHTML = `<td>
66
+ <select class="netid-select"
67
+ onchange="handleCharacterDropdown(this.value, '${character.characterName}')" id = "dropdown">
68
+ <option value="">
69
+ ${character.characterName}
70
+ </option>
71
+ <option value="delete">Delete Character</option>
72
+ </select>
73
+ </td>
74
+ <td>${character.showName}</td>
75
+ <td>${character.showSemester}</td>
76
+ <td>${character.firstName} ${character.lastName}</td>
77
+ <td>${character.netID}</td>
78
+ <td>${character.showID}</td>`;
79
+ tableBody.appendChild(row);
80
+ });
81
+ });
82
+ }
83
+
84
+ const FILTER_DROPDOWN_MAP = {
85
+ character: [
86
+ { value: "netID,c", label: "NetID" },
87
+ { value: "firstName,s", label: "First Name" },
88
+ { value: "lastName,s", label: "Last Name" },
89
+ { value: "showID,sh", label: "Show ID" },
90
+ { value: "characterName,c", label: "Character Name" },
91
+ { value: "showName,sh", label: "Show Name" },
92
+ { value: "yearSemester,sh", label: "Show Semester" },
93
+ ],
94
+ };
95
+
96
+ //splits value so that the correct table is referenced in the backend
97
+ function splitValue(stringToSplit) {
98
+ const splitValues = stringToSplit.split(",");
99
+ return splitValues;
100
+ }
101
+
102
+ function populateFilterDropdown() {
103
+ const select = document.getElementById("filter-column");
104
+ select.innerHTML = "";
105
+
106
+ const options = FILTER_DROPDOWN_MAP["character"];
107
+
108
+ if (!options) return;
109
+
110
+ options.forEach((opt) => {
111
+ const optionElement = document.createElement("option");
112
+ optionElement.value = opt.value; // this is sent to the backend
113
+ optionElement.textContent = opt.label; // this is displayed to the user
114
+ select.appendChild(optionElement);
115
+ });
116
+ }
117
+
118
+ function getShowIDFromName(showName) {
119
+ return fetch(`/shows/getShowID?showName=${encodeURIComponent(showName)}`)
120
+ .then((response) => response.json())
121
+ .then((data) => {
122
+ return data.showID;
123
+ });
124
+ }
125
+
126
+ function clearInput(elementId) {
127
+ document.getElementById(elementId).value = "";
128
+ }
129
+
130
+ async function addCharacter() {
131
+ // console.log(document.getElementById("showName").value);
132
+ // console.log(document.getElementById("netIDInput").value);
133
+ // console.log(document.getElementById("characterName").value);
134
+ const formData = new URLSearchParams();
135
+ formData.append("characterName",document.getElementById("characterName").value);
136
+ formData.append("showID", document.getElementById("showID").value);
137
+ formData.append("netID", document.getElementById("netIDInput").value);
138
+
139
+ const response = await fetch("/characters/add", {
140
+ method: "POST",
141
+ headers: {
142
+ "Content-Type": "application/x-www-form-urlencoded",
143
+ },
144
+ body: formData.toString(),
145
+ });
146
+
147
+ if (response.ok) {
148
+ alert("Character added successfully!");
149
+ document.getElementById("add-character-form").reset();
150
+ window.location.href = "/characters/loadpage";
151
+ } else {
152
+ alert("Error adding character.");
153
+ }
154
+ }
155
+
156
+
src/main/resources/static/crewScript.js ADDED
@@ -0,0 +1,117 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ function loadCrew(){
2
+ const urlParams = new URLSearchParams(window.location.search);
3
+ const netID = urlParams.get("netID");
4
+
5
+ if(netID){
6
+ document.getElementById("filter-input").value = netID;
7
+ processFilter();
8
+ } else{
9
+ fetch("/crew/getAll")
10
+ .then((response) => response.json())
11
+ .then((data) => {
12
+ const tableBody = document.getElementById("crew-table-body");
13
+ tableBody.innerHTML = "";
14
+
15
+ data.forEach((crew) => {
16
+ const row = document.createElement("tr");
17
+
18
+ row.innerHTML = `
19
+ <td>
20
+ <a href="/student/loadpage?netID=${crew.crewID}">
21
+ ${crew.crewID}
22
+ </a>
23
+ </td>
24
+ <td class = "sticky">${crew.firstName} ${crew.lastName}</td>
25
+ <td>${crew.wigTrained}</td>
26
+ <td>${crew.makeupTrained}</td>
27
+ <td>${crew.musicReading}</td>
28
+ <td>${crew.lighting}</td>
29
+ <td>${crew.sound}</td>
30
+ <td>${crew.specialty}</td>
31
+ <td>${crew.notes}</td>
32
+ `;
33
+
34
+ tableBody.appendChild(row);
35
+ });
36
+ })
37
+ .catch((error) => console.error("Error fetching crew data:", error));s
38
+ }
39
+
40
+ }
41
+
42
+
43
+ function processFilter() {
44
+ const filterValue = document.getElementById("filter-input").value;
45
+
46
+ fetch(`/crew/filterBy?value=${filterValue}`)
47
+ .then((res) => res.json())
48
+ .then((data) => {
49
+ const tableBody = document.getElementById(`crew-table-body`);
50
+ tableBody.innerHTML = "";
51
+
52
+ data.forEach((crew) => {
53
+ const row = document.createElement("tr");
54
+ row.innerHTML = `
55
+ <td>
56
+ <a href="/student/loadpage?netID=${crew.crewID}">
57
+ ${crew.crewID}
58
+ </a>
59
+ </td>
60
+ <td class = "sticky">${crew.firstName} ${crew.lastName}</td>
61
+ <td>${crew.wigTrained}</td>
62
+ <td>${crew.makeupTrained}</td>
63
+ <td>${crew.musicReading}</td>
64
+ <td>${crew.lighting}</td>
65
+ <td>${crew.sound}</td>
66
+ <td>${crew.specialty}</td>
67
+ <td>${crew.notes}</td>
68
+ `;
69
+ tableBody.appendChild(row);
70
+ });
71
+ });
72
+ }
73
+
74
+ function appendIfNotEmpty(formData, key, elementId) {
75
+ const val = document.getElementById(elementId).value;
76
+ if (val !== "") formData.append(key, val);
77
+ }
78
+
79
+ async function addCrew(){
80
+ const formData = new URLSearchParams();
81
+
82
+ appendIfNotEmpty(formData, "crewID", "netIDInput");
83
+ appendIfNotEmpty(formData, "firstName", "firstName");
84
+ appendIfNotEmpty(formData, "lastName", "lastName");
85
+ appendIfNotEmpty(formData, "wigTrained", "wigTrained");
86
+ appendIfNotEmpty(formData, "makeupTrained", "makeupTrained");
87
+ appendIfNotEmpty(formData, "musicReading", "musicReading");
88
+ appendIfNotEmpty(formData, "lighting", "lighting");
89
+ appendIfNotEmpty(formData, "sound", "sound");
90
+ appendIfNotEmpty(formData, "specialty", "specialty");
91
+ appendIfNotEmpty(formData, "notes", "notes");
92
+
93
+ const response = await fetch("/crew/addCrew", {
94
+ method: "POST",
95
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
96
+ body: formData.toString(),
97
+ });
98
+
99
+ const text = await response.text();
100
+
101
+ if (response.ok) {
102
+ alert(text);
103
+ document.getElementById("add-crew-form").reset();
104
+ window.location.href = "/crew/loadpage";
105
+ } else {
106
+ alert("Error adding crew: " + text);
107
+ }
108
+
109
+
110
+ if (response.ok) {
111
+ alert("Crew added successfully!");
112
+ document.getElementById("add-crew-form").reset();
113
+ window.location.href = "/crew/loadpage";
114
+ } else {
115
+ alert("Error adding crew.");
116
+ }
117
+ }
src/main/resources/static/script.js ADDED
@@ -0,0 +1,183 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //this function processes the filter request and updates the table accordingly
2
+
3
+ function clearInput(elementId) {
4
+ document.getElementById(elementId).value = "";
5
+ }
6
+
7
+ function updatePlaceholder() {
8
+ const select = document.getElementById("filter-column");
9
+ const input = document.getElementById("filter-input");
10
+
11
+ const selectedLabel = select.options[select.selectedIndex].text;
12
+
13
+ // Update placeholder
14
+ input.placeholder = `Search by ${selectedLabel}`;
15
+ }
16
+
17
+ function findNetIDFromName(value, firstLastNet, page) {
18
+ return fetch(`/student/filterBy?column=${firstLastNet}&value=${value}`)
19
+ .then((res) => res.json())
20
+ .then((data) => {
21
+ const select = document.getElementById("student-select");
22
+
23
+ select.innerHTML = "";
24
+
25
+ const noneFound = document.createElement("option");
26
+ noneFound.innerHTML = "No students found";
27
+
28
+ data.forEach((student) => {
29
+ const option = document.createElement("option");
30
+
31
+ option.value = JSON.stringify({
32
+ netID: student.netID,
33
+ firstName: student.firstName,
34
+ lastName: student.lastName,
35
+ });
36
+
37
+ option.textContent = `${student.firstName} ${student.lastName} (${student.netID})`;
38
+ select.appendChild(option);
39
+ });
40
+
41
+ if (data.length > 0) {
42
+ document.getElementById(`add${page}Button`).disabled = false;
43
+ if (data.length > 4) {
44
+ select.size = 4; // limit size to 4 if more than 4 entries
45
+ } else {
46
+ select.size = data.length;
47
+ }
48
+ } else {
49
+ select.size = 0;
50
+ document.getElementById(`add${page}Button`).disabled = true;
51
+ select.appendChild(noneFound);
52
+ }
53
+
54
+ // Return number of matching entries
55
+ return data.length;
56
+ })
57
+ .catch((error) => {
58
+ console.error("Error fetching student data:", error);
59
+
60
+ return 0; // return 0 on error
61
+ });
62
+ }
63
+
64
+ function addSetNetID(selectElement, page) {
65
+ if (!selectElement.value) return;
66
+
67
+ const data = JSON.parse(selectElement.value);
68
+ findNetIDFromName(data.netID, "netID", page);
69
+
70
+ document.getElementById("firstName").value = data.firstName;
71
+ document.getElementById("lastName").value = data.lastName;
72
+ document.getElementById("netIDInput").value = data.netID;
73
+ }
74
+
75
+ function addEventListeners(page) {
76
+ document.getElementById("netIDInput").addEventListener("input", function () {
77
+ const netID = this.value.trim();
78
+ if (netID !== "") {
79
+ findNetIDFromName(netID, "netID", page);
80
+ document.getElementById("student-select").hidden = false;
81
+ }
82
+ else{
83
+ findNetIDFromName('', 'netID', 'Crew');
84
+ }
85
+ });
86
+ document.getElementById("firstName").addEventListener("input", function () {
87
+ const firstName = this.value.trim();
88
+ if (firstName !== "") {
89
+ findNetIDFromName(firstName, "firstName", page);
90
+ document.getElementById("student-select").hidden = false;
91
+ }
92
+ else{
93
+ findNetIDFromName('', 'netID', 'Crew');
94
+ }
95
+ });
96
+
97
+ document.getElementById("lastName").addEventListener("input", function () {
98
+ const lastName = this.value.trim();
99
+ if (lastName !== "") {
100
+ findNetIDFromName(lastName, "lastName", page);
101
+ document.getElementById("student-select").hidden = false;
102
+ }
103
+ else{
104
+ findNetIDFromName('', 'netID', 'Crew');
105
+ }
106
+ });
107
+ }
108
+
109
+ function searchByShowAtt(searchBy, searchValue, page) {
110
+ return fetch(`/shows/getShowIDName?searchBy=${searchBy}&searchValue=${searchValue}`)
111
+ .then((res) => res.json())
112
+ .then((data) => {
113
+ const select = document.getElementById("show-select");
114
+ select.innerHTML = "";
115
+
116
+ const noneFound = document.createElement("option");
117
+ noneFound.innerHTML = "No shows found";
118
+
119
+ data.forEach((show) => {
120
+ const option = document.createElement("option");
121
+
122
+ option.value = JSON.stringify({
123
+ showID: show.showID,
124
+ showName: show.showName,
125
+ yearSemester: show.yearSemester,
126
+ });
127
+
128
+ document.getElementById("showID").value=show.showID;
129
+ option.textContent = `${show.showName} (${show.yearSemester})`;
130
+ select.appendChild(option);
131
+ });
132
+
133
+ if (data.length > 0) {
134
+ document.getElementById(`add${page}Button`).disabled = false;
135
+
136
+ if (data.length > 4) {
137
+ select.size = 4;
138
+ } else {
139
+ select.size = data.length;
140
+ }
141
+ } else {
142
+ console.log("penisballs");
143
+ select.size = 0;
144
+ document.getElementById(`add${page}Button`).disabled = true;
145
+ select.appendChild(noneFound);
146
+ }
147
+
148
+ return data.length;
149
+ })
150
+ .catch((error) => {
151
+ console.error("Error fetching show data:", error);
152
+ return 0;
153
+ });
154
+ }
155
+
156
+
157
+ function addShowEventListeners(page) {
158
+ document.getElementById("showName").addEventListener("input", function () {
159
+ const selectedOption = this.value.trim();
160
+ if (selectedOption !== "") {
161
+ searchByShowAtt("showName", selectedOption, page);
162
+ document.getElementById("show-select").hidden = false;
163
+ }
164
+ });
165
+
166
+ document.getElementById("yearSemester").addEventListener("input", function () {
167
+ const selectedOption = this.value.trim();
168
+ if (selectedOption !== "") {
169
+ searchByShowAtt("yearSemester", selectedOption, page);
170
+ document.getElementById("show-select").hidden = false;
171
+ }
172
+ });
173
+ }
174
+
175
+ function addSetShow(selectElement, page){
176
+ if (!selectElement.value) return;
177
+
178
+ const data = JSON.parse(selectElement.value);
179
+
180
+ searchByShowAtt("showName", data.showName, page)
181
+ document.getElementById("showName").value = data.showName;
182
+ document.getElementById("yearSemester").value= data.yearSemester;
183
+ }
src/main/resources/static/showScript.js ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ function loadShows() {
2
+ const urlParams = new URLSearchParams(window.location.search);
3
+ const netID = urlParams.get("netID");
4
+
5
+ if(netID){
6
+ document.getElementById("filter-input").value = netID;
7
+ processFilter();
8
+ } else{
9
+ fetch("/shows/getAll")
10
+ .then((response) => response.json())
11
+ .then((data) => {
12
+ const tableBody = document.getElementById("show-table-body");
13
+ tableBody.innerHTML = "";
14
+
15
+ data.forEach((show) => {
16
+ const row = document.createElement("tr");
17
+ row.innerHTML = `
18
+ <td>${show.showID}</td>
19
+ <td>${show.showName}</td>
20
+ <td>${show.yearSemester}</td>
21
+ <td>${show.director}</td>
22
+ <td>${show.genre}</td>
23
+ <td>${show.playWright}</td>
24
+ `;
25
+ tableBody.appendChild(row);
26
+ });
27
+ })
28
+ .catch((error) => console.error("Error loading shows:", error));
29
+ }
30
+ }
31
+
32
+ // function processFilter(){
33
+ // const filterValue = document.getElementById("filter-input").value;
34
+
35
+ // fetch(`/crew/filterBy?value=${filterValue}`)
36
+ // .then((res) => res.json())
37
+ // .then((crew) => {
38
+ // const tableBody = document.getElementById(`crew-table-body`);
39
+ // tableBody.innerHTML = "";
40
+
41
+ // data.forEach((item) => {
42
+ // const row = document.createElement("tr");
43
+ // row.innerHTML = `
44
+ // <td>
45
+ // `
46
+
47
+ // })
48
+
49
+
50
+ // })
51
+ // }
src/main/resources/static/studentScript.js ADDED
@@ -0,0 +1,250 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ function loadStudents() {
2
+ const urlParams = new URLSearchParams(window.location.search);
3
+ const netID = urlParams.get("netID");
4
+
5
+ fetch("/student/getAll")
6
+ .then((response) => response.json())
7
+ .then((data) => {
8
+ const tableBody = document.getElementById("student-table-body");
9
+ tableBody.innerHTML = "";
10
+
11
+ // If netID exists, filter data in JS; otherwise show all
12
+ const filteredData = netID ? data.filter((s) => s.netID === netID) : data;
13
+
14
+ filteredData.forEach((student) => {
15
+ const row = document.createElement("tr");
16
+ row.innerHTML = `
17
+ <td>
18
+ <select class="netid-select"
19
+ onchange="handleNetIdDropdown(this.value, '${student.netID}')">
20
+ <option value="" selected>${student.netID}</option>
21
+ <option value="roles">Previous Roles</option>
22
+ <option value="shows">Previous Shows</option>
23
+ <option value="crew">CrewPage</option>
24
+ <option value="actor">ActorPage</option>
25
+ <option value="delete">Delete Student</option>
26
+ <option value="edit">Edit Student</option>
27
+ </select>
28
+ </td>
29
+ <td>${student.firstName} ${student.lastName}</td>
30
+ <td>${student.gradeLevel}</td>
31
+ <td>${student.pronouns}</td>
32
+ <td>${student.specialNotes}</td>
33
+ <td>${student.email}</td>
34
+ <td>${student.allergies_sensitivities}</td>
35
+ `;
36
+ tableBody.appendChild(row);
37
+ });
38
+
39
+ // Only set filter input if netID exists
40
+ if (netID) {
41
+ document.getElementById("filter-column").value = "netID";
42
+ document.getElementById("filter-input").value = netID;
43
+ }
44
+ })
45
+ .catch((error) => console.error("Error fetching student data:", error));
46
+ }
47
+
48
+ //this function processes the filter request and updates the table accordingly
49
+ function processFilter(page) {
50
+ const filterBy = document.getElementById("filter-column").value;
51
+ const filterValue = document.getElementById("filter-input").value;
52
+
53
+ fetch(`/${page}/filterBy?column=${filterBy}&value=${filterValue}`)
54
+ .then((res) => res.json())
55
+ .then((data) => {
56
+ const tableBody = document.getElementById(`${page}-table-body`);
57
+ tableBody.innerHTML = "";
58
+
59
+ data.forEach((item) => {
60
+ const row = document.createElement("tr");
61
+ row.innerHTML = `
62
+ <td>
63
+ <select class="netid-select" onchange="handleNetIdDropdown(this.value, '${item.netID}')">
64
+ <option value="" selected>${item.netID}</option>
65
+ <option value="roles">Previous Roles</option>
66
+ <option value="shows">Previous Shows</option>
67
+ <option value="crew">CrewPage</option>
68
+ <option value="actor">ActorPage</option>
69
+ <option value="delete">Delete Student</option>
70
+ <option value="edit">Edit Student</option>
71
+ </select>
72
+ </td>
73
+ <td>${item.firstName} ${item.lastName}</td>
74
+ <td>${item.gradeLevel}</td>
75
+ <td>${item.pronouns}</td>
76
+ <td>${item.specialNotes}</td>
77
+ <td>${item.email}</td>
78
+ <td>${item.allergies_sensitivities}</td>
79
+ `;
80
+ tableBody.appendChild(row);
81
+ });
82
+ });
83
+ }
84
+
85
+ function clearInput(elementId) {
86
+ document.getElementById(elementId).value = "";
87
+ }
88
+
89
+ function handleNetIdDropdown(selectedValue, netID) {
90
+ if (!selectedValue) {
91
+ return;
92
+ }
93
+ if (selectedValue === "roles") {
94
+ window.location.href = `/characters/loadpage?netID=${netID}`;
95
+ }
96
+ if (selectedValue === "shows") {
97
+ window.location.href = `/student/${netID}/shows`;
98
+ }
99
+ if (selectedValue === "crew") {
100
+ window.location.href = `/crew/loadpage?netID=${netID}`;
101
+ }
102
+ if (selectedValue === "delete") {
103
+ deleteStudent(netID);
104
+ }
105
+ if (selectedValue === "edit") {
106
+ window.location.href = `/student/${netID}/editPage`;
107
+ }
108
+ if (selectedValue === "actor") {
109
+ window.location.href = `/actors/loadpage?netID=${netID}`;
110
+ }
111
+ }
112
+
113
+ async function editStudent(netID) {
114
+ const formData = new URLSearchParams();
115
+ formData.append("netID", document.getElementById("netID").value);
116
+ formData.append("firstName", document.getElementById("firstName").value);
117
+ formData.append("lastName", document.getElementById("lastName").value);
118
+ formData.append("gradeLevel", document.getElementById("gradeLevel").value);
119
+ formData.append("pronouns", document.getElementById("pronouns").value);
120
+ formData.append(
121
+ "specialNotes",
122
+ document.getElementById("specialNotes").value
123
+ );
124
+ formData.append("email", document.getElementById("email").value);
125
+ formData.append(
126
+ "allergies_sensitivities",
127
+ document.getElementById("allergies").value
128
+ );
129
+
130
+ const response = await fetch(`/student/${netID}/edit`, {
131
+ method: "POST",
132
+ headers: {
133
+ "Content-Type": "application/x-www-form-urlencoded",
134
+ },
135
+ body: formData.toString(),
136
+ });
137
+
138
+ if (response.ok) {
139
+ alert("Student edited successfully!");
140
+ document.getElementById("edit-student-form").reset();
141
+ window.location.href = "/student/loadpage";
142
+ } else {
143
+ alert("Error editing student.");
144
+ }
145
+ }
146
+
147
+ const FILTER_DROPDOWN_MAP = {
148
+ student: [
149
+ { value: "netID", label: "NetID" },
150
+ { value: "firstName", label: "First Name" },
151
+ { value: "lastName", label: "Last Name" },
152
+ { value: "gradeLevel", label: "Grade Level" },
153
+ { value: "allergies_sensitivities", label: "Allergies/Sensitivities" },
154
+ ],
155
+ };
156
+
157
+ function populateFilterDropdown() {
158
+ const select = document.getElementById("filter-column");
159
+ select.innerHTML = "";
160
+
161
+ const options = FILTER_DROPDOWN_MAP["student"];
162
+
163
+ if (!options) return;
164
+
165
+ options.forEach((opt) => {
166
+ const optionElement = document.createElement("option");
167
+ optionElement.value = opt.value; // this is sent to the backend
168
+ optionElement.textContent = opt.label; // this is displayed to the user
169
+ select.appendChild(optionElement);
170
+ });
171
+ }
172
+
173
+ async function addStudent() {
174
+ const formData = new URLSearchParams();
175
+ formData.append("netID", document.getElementById("netID").value);
176
+ formData.append("firstName", document.getElementById("firstName").value);
177
+ formData.append("lastName", document.getElementById("lastName").value);
178
+ formData.append("gradeLevel", document.getElementById("gradeLevel").value);
179
+ formData.append("pronouns", document.getElementById("pronouns").value);
180
+ formData.append(
181
+ "specialNotes",
182
+ document.getElementById("specialNotes").value
183
+ );
184
+ formData.append("email", document.getElementById("email").value);
185
+ formData.append("allergies", document.getElementById("allergies").value);
186
+
187
+ const response = await fetch("/student/add", {
188
+ method: "POST",
189
+ headers: {
190
+ "Content-Type": "application/x-www-form-urlencoded",
191
+ },
192
+ body: formData.toString(),
193
+ });
194
+
195
+ if (response.ok) {
196
+ alert("Student added successfully!");
197
+ document.getElementById("add-student-form").reset();
198
+ window.location.href = "/student/loadpage";
199
+ } else {
200
+ alert("Error adding student.");
201
+ }
202
+ }
203
+
204
+ function deleteStudent(netID) {
205
+ if (
206
+ !confirm(`Are you sure you want to delete student with NetID: ${netID}?`)
207
+ ) {
208
+ return;
209
+ }
210
+ const formData = new URLSearchParams();
211
+ formData.append("netID", netID);
212
+
213
+ fetch("/student/delete", {
214
+ method: "POST",
215
+ headers: {
216
+ "Content-Type": "application/x-www-form-urlencoded",
217
+ },
218
+ body: formData.toString(),
219
+ })
220
+ .then((response) => {
221
+ if (response.ok) {
222
+ alert("Student deleted successfully!");
223
+ loadStudents();
224
+ } else {
225
+ alert("Error deleting student.");
226
+ }
227
+ })
228
+ .catch((error) => console.error("Error deleting student:", error));
229
+ }
230
+
231
+ function validateNetID() {
232
+ document.getElementById("netID").addEventListener("input", function (e) {
233
+ let value = e.target.value;
234
+
235
+ // Only allow letters for first 3 chars
236
+ if (value.length <= 3) {
237
+ value = value.replace(/[^A-Za-z]/g, "");
238
+ }
239
+
240
+ // After 3 chars, allow only digits
241
+ if (value.length > 3) {
242
+ value = value.substring(0, 3) + value.substring(3).replace(/[^0-9]/g, "");
243
+ }
244
+
245
+ // Enforce max length 8
246
+ value = value.substring(0, 8);
247
+
248
+ e.target.value = value;
249
+ });
250
+ }
src/main/resources/static/style.css ADDED
@@ -0,0 +1,387 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ :root {
2
+ --baltic-blue: #005ca9ff;
3
+
4
+ --space-sm: clamp(0.25rem, 0.5vw, 0.75rem);
5
+ --space-md: clamp(0.5rem, 1vw, 1.25rem);
6
+ --space-lg: clamp(1rem, 2vw, 2.5rem);
7
+ --space-xl: clamp(2rem, 4vw, 4rem);
8
+
9
+ --font-sm: clamp(0.8rem, 1.2vw, 1rem);
10
+ --font-md: clamp(1rem, 1.5vw, 1.25rem);
11
+ --font-lg: clamp(1.25rem, 2vw, 2rem);
12
+ }
13
+
14
+ .page-background {
15
+ background: #F2EFEA;
16
+ padding: var(--space-lg);
17
+ place-items: center;
18
+ }
19
+
20
+ h1 {
21
+ text-decoration: underline;
22
+ text-align: center;
23
+ font-weight: bolder;
24
+ margin-bottom: var(--space-xl);
25
+ font-family: 'Times New Roman', Times, serif;
26
+ font-size: var(--font-lg);
27
+ background: rgb(255, 255, 255);
28
+ padding: 20px 40px;
29
+ border-radius: 15px;
30
+ box-shadow: 0 4px 15px rgba(0, 0, 0, 0.15);
31
+ display: center;
32
+ }
33
+
34
+ table {
35
+ width: 100%;
36
+ border-collapse: collapse;
37
+ margin: var(--space-lg) 0;
38
+ font-size: var(--font-md);
39
+ }
40
+
41
+ th,
42
+ td {
43
+ border: 1px solid black;
44
+ text-align: center;
45
+ padding: var(--space-sm);
46
+ background-color: white;
47
+ }
48
+
49
+ td {
50
+ height: clamp(24px, 4vw, 40px);
51
+ }
52
+
53
+ .netid-select {
54
+ appearance: none;
55
+ -webkit-appearance: none;
56
+ -moz-appearance: none;
57
+ background-color: lightskyblue;
58
+ border: 1px solid black;
59
+ border-radius: 8px;
60
+ padding: var(--space-sm) var(--space-lg) var(--space-sm) var(--space-md);
61
+ font-size: var(--font-md);
62
+ font-weight: bolder;
63
+ font-family: 'Franklin Gothic Medium', 'Arial Narrow', Arial, sans-serif;
64
+ color: #333;
65
+ cursor: pointer;
66
+ outline: none;
67
+ transition: all 0.25s ease;
68
+ background-repeat: no-repeat;
69
+ background-position: right var(--space-md) center;
70
+ background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'><path fill='black' d='M0 0l5 6 5-6z'/></svg>");
71
+ }
72
+
73
+ .netid-select:hover {
74
+ border-color: black;
75
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
76
+ }
77
+
78
+ .netid-select:focus {
79
+ outline: black solid 1px;
80
+ background-color: #a0d8ef;
81
+ }
82
+
83
+ select option {
84
+ padding: var(--space-sm);
85
+ border: 0.5px solid black;
86
+ }
87
+
88
+ .filter-select {
89
+ appearance: none;
90
+ -webkit-appearance: none;
91
+ -moz-appearance: none;
92
+ background-color: #d7d7d7;
93
+ border: 1px solid black;
94
+ border-radius: 8px;
95
+ font-family: "times new roman", Times, serif;
96
+ font-weight: bolder;
97
+ padding: clamp(0.25rem, 0.6vw, 0.45rem) clamp(1.5rem, 2vw, 2rem) clamp(0.25rem, 0.6vw, 0.45rem) clamp(0.5rem, 1vw, 0.75rem);
98
+ font-size: clamp(0.85rem, 1.2vw, 1rem);
99
+ color: #333;
100
+ cursor: pointer;
101
+ outline: none;
102
+ transition: all 0.25s ease;
103
+ background-repeat: no-repeat;
104
+ background-position: right clamp(0.4rem, 1vw, 0.75rem) center;
105
+ background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'><path fill='black' d='M0 0l5 6 5-6z'/></svg>");
106
+ }
107
+
108
+ .filter-select:hover {
109
+ border-color: black;
110
+ background-color: lightskyblue;
111
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15);
112
+ }
113
+
114
+ .filter-select:focus {
115
+ outline: black solid 1px;
116
+ background-color: lightskyblue;
117
+ }
118
+
119
+ .filter-select option {
120
+ padding: 8px;
121
+ border: 0.5px solid black;
122
+ }
123
+
124
+ .home-buttons {
125
+ background-color: var(--baltic-blue);
126
+ border: none;
127
+ padding: var(--space-md) var(--space-lg);
128
+ text-align: center;
129
+ display: inline-block;
130
+ font-size: var(--font-md);
131
+ margin: var(--space-sm) 0;
132
+ cursor: pointer;
133
+ border-radius: 8px;
134
+ width: clamp(200px, 100%, 400px);
135
+ font-family: 'Times New Roman', Times, serif;
136
+ text-decoration: underline;
137
+ font-variant: small-caps;
138
+ font-weight: bold;
139
+ color: rgb(167, 217, 234);
140
+ transition: 0.25s ease;
141
+ }
142
+
143
+ .home-buttons:hover {
144
+ background-color: lightskyblue;
145
+ color: black;
146
+ transform: translateY(-3px);
147
+ background: #1d6eff;
148
+ box-shadow: 0 6px 12px rgba(0, 0, 0, 0.15);
149
+ }
150
+
151
+ .buttons-container {
152
+ align-items: center;
153
+ display: flex;
154
+ flex-direction: column;
155
+ margin-top: var(--space-lg);
156
+ background: white;
157
+ padding: 30px 40px;
158
+ border-radius: 16px;
159
+ box-shadow: 0 8px 20px rgba(0,0,0,0.12);
160
+ display: flex;
161
+ flex-direction: column;
162
+ gap: 15px;
163
+ }
164
+
165
+ .search-bar {
166
+ width: 100%;
167
+ max-width: 350px;
168
+ padding: clamp(0.4rem, 1vw, 0.75rem) clamp(1.5rem, 2vw, 2rem);
169
+ font-size: clamp(0.9rem, 1.2vw, 1.1rem);
170
+ background-color: #f0f0f0;
171
+ border: 1px solid black;
172
+ border-radius: 12px;
173
+ outline: none;
174
+ transition: all 0.3s ease;
175
+ background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='18' height='18' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><circle cx='11' cy='11' r='8'></circle><line x1='21' y1='21' x2='16.65' y2='16.65'></line></svg>");
176
+ background-repeat: no-repeat;
177
+ background-position: 10px center;
178
+ background-size: 18px;
179
+ padding-left: clamp(2.5rem, 4vw, 3.2rem);
180
+ margin-bottom: var(--space-md);
181
+ }
182
+
183
+ .search-bar::placeholder {
184
+ color: #666;
185
+ opacity: 0.8;
186
+ font-style: italic;
187
+ transition: color 0.3s ease;
188
+ }
189
+
190
+ .search-bar:hover {
191
+ background-color: #e8f4fb;
192
+ border-color: #888;
193
+ }
194
+
195
+ .search-bar:focus {
196
+ background-color: #a0d8ef;
197
+ border-color: #1a73e8;
198
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
199
+ transform: translateY(-2px) scale(1.03);
200
+ }
201
+
202
+ .search-bar:focus::placeholder {
203
+ color: #333;
204
+ }
205
+
206
+ .basicButton {
207
+ background-color: lightskyblue;
208
+ color: black;
209
+ border: black solid 2px;
210
+ padding: var(--space-sm) var(--space-lg);
211
+ border-radius: 8px;
212
+ font-size: var(--font-md);
213
+ font-family: 'Times New Roman', Times, serif;
214
+ font-weight: bold;
215
+ text-transform: uppercase;
216
+ cursor: pointer;
217
+ transition: 0.25s ease;
218
+ }
219
+
220
+ .basicButton:hover {
221
+ background: #1d6eff;
222
+ color: rgb(167, 217, 234);
223
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
224
+ transform: translateY(-2px);
225
+ }
226
+
227
+ .basicButton:active {
228
+ transform: translateY(0px);
229
+ }
230
+
231
+ .basicButton:disabled{
232
+ background-color: grey;
233
+ color: darkgrey;
234
+ border: darkgrey solid 2px;
235
+ cursor: not-allowed;
236
+ box-shadow: none;
237
+ transform: translateY(0px);
238
+ }
239
+
240
+ .addElementLabel {
241
+ display: block;
242
+ font-family: 'Times New Roman', Times, serif;
243
+ font-size: clamp(1.2rem, 1.5vw, 1.5rem);
244
+ text-decoration: underline;
245
+ align-items: center;
246
+ margin-bottom: clamp(0.25rem, 0.6vw, 0.5rem);
247
+ color: #04080f;
248
+ font-weight: bold;
249
+ }
250
+
251
+ input.formInput {
252
+ width: 100%;
253
+ padding: 10px 15px;
254
+ margin-bottom: 15px;
255
+ border: 1px solid black;
256
+ border-radius: 8px;
257
+ font-size: 1rem;
258
+ color: black;
259
+ background-color: #f9f9f9;
260
+ transition: border-color 0.3s, box-shadow 0.3s;
261
+ }
262
+
263
+ input.formInput:focus {
264
+ border-color: #005ca9;
265
+ box-shadow: 0 0 5px rgba(0, 92, 169, 0.5);
266
+ outline: none;
267
+ }
268
+
269
+ input.formInput::placeholder {
270
+ color: #888;
271
+ font-style: italic;
272
+ }
273
+
274
+ .wide-table-container {
275
+ overflow-x: auto;
276
+ width: 100%;
277
+ }
278
+
279
+ .styled-table {
280
+ width: 100%;
281
+ border-collapse: collapse;
282
+ min-width: 100px;
283
+ background-color: #fff;
284
+ font-size: 20px;
285
+ }
286
+
287
+ .styled-table th,
288
+ .styled-table td {
289
+ border: 1px solid black;
290
+ padding: 8px 12px;
291
+ text-align: left;
292
+ }
293
+
294
+ .styled-table thead tr {
295
+ background-color: #f2f2f2;
296
+ font-weight: bold;
297
+ }
298
+
299
+ .styled-table tbody tr:nth-child(even) {
300
+ background-color: #fafafa;
301
+ }
302
+
303
+ .styled-table tbody tr:hover {
304
+ background-color: #f1f1f1;
305
+ }
306
+
307
+
308
+ .sticky {
309
+ position: sticky;
310
+ left: 0;
311
+ background: lightskyblue;
312
+ z-index: 2;
313
+ border-right: 1px solid black;
314
+ }
315
+
316
+ select option {
317
+ padding: 8px 12px;
318
+ background-color: #FFFFFF;
319
+ color: #333;
320
+ border-bottom: 1px solid #E5E7EB;
321
+ font-size: 15px;
322
+ }
323
+
324
+ .table-select {
325
+ display: block;
326
+ margin: 1rem auto;
327
+ width: 300px;
328
+ max-width: 90%;
329
+ padding: 0.5rem 1rem;
330
+ font-size: 1rem;
331
+ border: 1px solid #333;
332
+ border-radius: 8px;
333
+ background-color: #f0f0f0;
334
+ color: #333;
335
+ box-shadow: 1px 1px 3px rgba(0,0,0,0.2);
336
+ cursor: pointer;
337
+ }
338
+
339
+ .table-select:hover,
340
+ .table-select:focus {
341
+ border-color: #007bff;
342
+ outline: none;
343
+ background-color: #e6f0ff;
344
+ }
345
+ .input-with-button {
346
+ display: flex;
347
+ align-items: center;
348
+ gap: 5px;
349
+ width: 100%;
350
+ max-width: 400px;
351
+ margin-bottom: var(--space-md); /* spacing below input */
352
+ }
353
+
354
+ .input-with-button input.formInput {
355
+ flex: 1;
356
+ height: 36px;
357
+ }
358
+
359
+ .square-button {
360
+ width: 36px;
361
+ height: 36px;
362
+ background-color: lightskyblue;
363
+ border: 1px solid black;
364
+ border-radius: 6px;
365
+ cursor: pointer;
366
+ font-size: 1.2rem;
367
+ display: flex;
368
+ align-items: center;
369
+ justify-content: center;
370
+ padding: 0;
371
+ transition: 0.2s ease;
372
+ }
373
+
374
+ .square-button:hover {
375
+ background-color: #1d6eff;
376
+ color: white;
377
+ transform: scale(1.05);
378
+ }
379
+
380
+
381
+ .checkBox {
382
+ width: 18px;
383
+ height: 18px;
384
+ accent-color: #005ca9; /* Modern browser color for checkmark */
385
+ }
386
+
387
+
src/main/resources/templates/actor/actors.html ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title>Creighton Theater Database</title>
6
+ <link rel="stylesheet" href="/style.css">
7
+ <script src="/actorScript.js"></script>
8
+ </head>
9
+
10
+ <body onload="loadActors();" class="page-background">
11
+ <button onclick="location.href='/'" class="basicButton">Home</button>
12
+ <h1 style="text-align: center;">Actor Page</h1>
13
+ <button onclick="location.href='/actor/add'" class="basicButton" style="float: right;">Add New Actor</button>
14
+ <label for="filter-input" style="margin-right: 10px;">Filter By Net ID:</label>
15
+ <input type="text" placeholder="Search by NetID" id="filter-input" class="search-bar">
16
+
17
+ <div class="wide-table-container">
18
+ <table class="styled-table" style="border-collapse:collapse">
19
+ <thead>
20
+ <tr>
21
+ <th>NetID</th>
22
+ <th class="sticky">Name</th>
23
+ <th>Years Acting Experience</th>
24
+ <th>Skin Tone</th>
25
+ <th>Piercings</th>
26
+ <th>Hair Color</th>
27
+ <th>Previous Injuries</th>
28
+ <th>Special Notes</th>
29
+ <th>Height</th>
30
+ <th>Ring Size</th>
31
+ <th>Shoe Size</th>
32
+ <th>Head Circ</th>
33
+ <th>Neck Base</th>
34
+ <th>Chest</th>
35
+ <th>Waist</th>
36
+ <th>High Hip</th>
37
+ <th>Lolocw Hip</th>
38
+ <th>Armseye to Armseye (Front)</th>
39
+ <th>Neck to Waist (Front)</th>
40
+ <th>Armseye to Armseye (Back)</th>
41
+ <th>Neck to Waist (Back)</th>
42
+ <th>Center Back to Wrist</th>
43
+ <th>Outsleeve to Wrist</th>
44
+ <th>Outseam Below Knee</th>
45
+ <th>Outseam to Ankle</th>
46
+ <th>Outseam to Floor</th>
47
+ <th>Other Notes</th>
48
+ <th>Photo</th>
49
+
50
+
51
+ </tr>
52
+ </thead>
53
+ <tbody id="actor-table-body">
54
+ </tbody>
55
+ </table>
56
+ </div>
57
+ <script>
58
+ //dynamically updates the page as the user types into filter-input
59
+ const filterInput = document.getElementById("filter-input");
60
+ filterInput.addEventListener("input", () => {
61
+ processFilter();
62
+ });</script>
63
+
64
+
65
+ </body>
src/main/resources/templates/actor/addActors.html ADDED
@@ -0,0 +1,122 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <head>
3
+ <meta charset="UTF-8">
4
+ <title>Creighton Theater Database</title>
5
+ <link rel="stylesheet" href="/style.css">
6
+ <script src="/actorScript.js"></script>
7
+ <script src = "/script.js"></script>
8
+ </head>
9
+
10
+ <body class="page-background" onload="findNetIDFromName('', 'netID', 'Actor'); addEventListeners('Actor');">
11
+
12
+ <button onclick="location.href='/'" class="basicButton">Home</button>
13
+ <button onclick="location.href='/actors/loadpage'" class="basicButton"
14
+ style="font-size: smaller; margin-bottom: var(--space-md);">Back to Actor List</button>
15
+
16
+ <h1 style="text-align: center;">ADD ACTOR PAGE</h1>
17
+
18
+ <form id="add-actor-form">
19
+ <div class="input-with-button">
20
+ <label for="netID" class="addElementLabel">NetID:</label>
21
+ <input type="text" id="netIDInput" name="netID" class="formInput" required>
22
+ <button type="button" class="square-button"
23
+ onclick="clearInput('netIDInput'); clearInput('firstName'); clearInput('lastName'); findNetIDFromName('', 'netID', 'Character');">×</button>
24
+ </div>
25
+
26
+
27
+ <label for="firstName" class="addElementLabel">First Name:</label>
28
+ <input type="text" id="firstName" name="firstName" class="formInput">
29
+
30
+ <label for="lastName" class="addElementLabel">Last Name:</label>
31
+ <input type="text" id="lastName" name="lastName" class="formInput">
32
+
33
+ <div style="text-align: center;">
34
+ <select size="5" id="student-select" onclick="addSetNetID(this, 'Actor')"></select>
35
+ <option value="netID"></option>
36
+ </div>
37
+
38
+
39
+ <label for="yearsActingExperience" class="addElementLabel">Years Acting Experience:</label>
40
+ <input type="text" id="yearsActingExperience" name="yearsActingExperience" class="formInput">
41
+
42
+ <label for="skinTone" class="addElementLabel">Skin Tone:</label>
43
+ <input type="text" id="skinTone" name="skinTone" class="formInput">
44
+
45
+ <label for="piercings" class="addElementLabel">Piercings:</label>
46
+ <input type="text" id="piercings" name="piercings" class="formInput">
47
+
48
+ <label for="hairColor" class="addElementLabel">Hair Color:</label>
49
+ <input type="text" id="hairColor" name="hairColor" class="formInput">
50
+
51
+ <label for="previousInjuries" class="addElementLabel">Previous Injuries:</label>
52
+ <input type="text" id="previousInjuries" name="previousInjuries" class="formInput">
53
+
54
+ <label for="specialNotes" class="addElementLabel">Special Notes:</label>
55
+ <input type="text" id="specialNotes" name="specialNotes" class="formInput">
56
+
57
+ <label for="height" class="addElementLabel">Height:</label>
58
+ <input type="text" id="height" name="height" class="formInput">
59
+
60
+ <label for="ringSize" class="addElementLabel">Ring Size:</label>
61
+ <input type="text" id="ringSize" name="ringSize" class="formInput">
62
+
63
+ <label for="shoeSize" class="addElementLabel">Shoe Size:</label>
64
+ <input type="text" id="shoeSize" name="shoeSize" class="formInput">
65
+
66
+ <label for="headCirc" class="addElementLabel">Head Circumference:</label>
67
+ <input type="text" id="headCirc" name="headCirc" class="formInput">
68
+
69
+ <label for="neckBase" class="addElementLabel">Neck Base:</label>
70
+ <input type="text" id="neckBase" name="neckBase" class="formInput">
71
+
72
+ <label for="chest" class="addElementLabel">Chest:</label>
73
+ <input type="text" id="chest" name="chest" class="formInput">
74
+
75
+ <label for="waist" class="addElementLabel">Waist:</label>
76
+ <input type="text" id="waist" name="waist" class="formInput">
77
+
78
+ <label for="highHip" class="addElementLabel">High Hip:</label>
79
+ <input type="text" id="highHip" name="highHip" class="formInput">
80
+
81
+ <label for="lowHip" class="addElementLabel">Low Hip:</label>
82
+ <input type="text" id="lowHip" name="lowHip" class="formInput">
83
+
84
+ <label for="armseyeToArmseyeFront" class="addElementLabel">Armseye to Armseye (Front):</label>
85
+ <input type="text" id="armseyeToArmseyeFront" name="armseyeToArmseyeFront" class="formInput">
86
+
87
+ <label for="neckToWaistFront" class="addElementLabel">Neck to Waist (Front):</label>
88
+ <input type="text" id="neckToWaistFront" name="neckToWaistFront" class="formInput">
89
+
90
+ <label for="armseyeToArmseyeBack" class="addElementLabel">Armseye to Armseye (Back):</label>
91
+ <input type="text" id="armseyeToArmseyeBack" name="armseyeToArmseyeBack" class="formInput">
92
+
93
+ <label for="neckToWaistBack" class="addElementLabel">Neck to Waist (Back):</label>
94
+ <input type="text" id="neckToWaistBack" name="neckToWaistBack" class="formInput">
95
+
96
+ <label for="centerBackToWrist" class="addElementLabel">Center Back to Wrist:</label>
97
+ <input type="text" id="centerBackToWrist" name="centerBackToWrist" class="formInput">
98
+
99
+ <label for="outsleeveToWrist" class="addElementLabel">Outsleeve to Wrist:</label>
100
+ <input type="text" id="outsleeveToWrist" name="outsleeveToWrist" class="formInput">
101
+
102
+ <label for="outseamBelowKnee" class="addElementLabel">Outseam Below Knee:</label>
103
+ <input type="text" id="outseamBelowKnee" name="outseamBelowKnee" class="formInput">
104
+
105
+ <label for="outseamToAnkle" class="addElementLabel">Outseam to Ankle:</label>
106
+ <input type="text" id="outseamToAnkle" name="outseamToAnkle" class="formInput">
107
+
108
+ <label for="outseamToFloor" class="addElementLabel">Outseam to Floor:</label>
109
+ <input type="text" id="outseamToFloor" name="outseamToFloor" class="formInput">
110
+
111
+ <label for="otherNotes" class="addElementLabel">Other Notes:</label>
112
+ <input type="text" id="otherNotes" name="otherNotes" class="formInput">
113
+
114
+
115
+ <button type="button" onclick="addActor()" class="basicButton" id = "addActorButton">
116
+ Add Actor
117
+ </button>
118
+
119
+ </form>
120
+
121
+
122
+ </body>
src/main/resources/templates/actor/editActor.html ADDED
@@ -0,0 +1,153 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title>Creighton Theater Database</title>
6
+ <link rel="stylesheet" href="/style.css">
7
+ <script src="/actorScript.js"> </script>
8
+
9
+ </head>
10
+
11
+ <body class="page-background">
12
+
13
+ <button onclick="location.href='/'" class="basicButton">Home</button>
14
+ <button onclick="location.href='/actors/loadpage'" class="basicButton"
15
+ style="font-size: smaller; margin-bottom: var(--space-md);">Back to Actor List</button>
16
+ <h1 style="text-align: center;">EDIT ACTOR PAGE</h1>
17
+
18
+ <form id="edit-actor-form">
19
+
20
+ <!-- READ-ONLY FIELDS -->
21
+ <label class="addElementLabel">NetID:</label>
22
+ <p class="displayField" th:text="${actor.netID}"></p>
23
+ <input type="hidden" id="netID" name="netID" th:value="${actor.netID}">
24
+ <br><br>
25
+
26
+ <label class="addElementLabel">First Name:</label>
27
+ <p class="displayField" th:text="${actor.firstName}"></p>
28
+ <input type="hidden" id="firstName" name="firstName" th:value="${actor.firstName}">
29
+ <br><br>
30
+
31
+ <label class="addElementLabel">Last Name:</label>
32
+ <p class="displayField" th:text="${actor.lastName}"></p>
33
+ <input type="hidden" id="lastName" name="lastName" th:value="${actor.lastName}">
34
+ <br><br>
35
+
36
+ <!-- EDITABLE FIELDS -->
37
+
38
+ <label class="addElementLabel">Years Acting Experience:</label>
39
+ <input type="number" id="yearsActingExperience" name="yearsActingExperience"
40
+ th:value="${actor.yearsActingExperience}" class="formInput">
41
+ <br><br>
42
+
43
+ <label class="addElementLabel">Skin Tone:</label>
44
+ <input type="text" id="skinTone" name="skinTone" th:value="${actor.skinTone}" class="formInput">
45
+ <br><br>
46
+
47
+ <label class="addElementLabel">Piercings:</label>
48
+ <input type="text" id="piercings" name="piercings" th:value="${actor.piercings}" class="formInput">
49
+ <br><br>
50
+
51
+ <label class="addElementLabel">Hair Color:</label>
52
+ <input type="text" id="hairColor" name="hairColor" th:value="${actor.hairColor}" class="formInput">
53
+ <br><br>
54
+
55
+ <label class="addElementLabel">Previous Injuries:</label>
56
+ <input type="text" id="previousInjuries" name="previousInjuries" th:value="${actor.previousInjuries}"
57
+ class="formInput">
58
+ <br><br>
59
+
60
+ <label class="addElementLabel">Special Notes:</label>
61
+ <input type="text" id="specialNotes" name="specialNotes" th:value="${actor.specialNotes}" class="formInput">
62
+ <br><br>
63
+
64
+ <label class="addElementLabel">Height:</label>
65
+ <input type="text" id="height" name="height" th:value="${actor.height}" class="formInput">
66
+ <br><br>
67
+
68
+ <label class="addElementLabel">Ring Size:</label>
69
+ <input type="text" id="ringSize" name="ringSize" th:value="${actor.ringSize}" class="formInput">
70
+ <br><br>
71
+
72
+ <label class="addElementLabel">Shoe Size:</label>
73
+ <input type="text" id="shoeSize" name="shoeSize" th:value="${actor.shoeSize}" class="formInput">
74
+ <br><br>
75
+
76
+ <label class="addElementLabel">Head Circumference:</label>
77
+ <input type="text" id="headCirc" name="headCirc" th:value="${actor.headCirc}" class="formInput">
78
+ <br><br>
79
+
80
+ <label class="addElementLabel">Neck Base:</label>
81
+ <input type="text" id="neckBase" name="neckBase" th:value="${actor.neckBase}" class="formInput">
82
+ <br><br>
83
+
84
+ <label class="addElementLabel">Chest:</label>
85
+ <input type="text" id="chest" name="chest" th:value="${actor.chest}" class="formInput">
86
+ <br><br>
87
+
88
+ <label class="addElementLabel">Waist:</label>
89
+ <input type="text" id="waist" name="waist" th:value="${actor.waist}" class="formInput">
90
+ <br><br>
91
+
92
+ <label class="addElementLabel">High Hip:</label>
93
+ <input type="text" id="highHip" name="highHip" th:value="${actor.highHip}" class="formInput">
94
+ <br><br>
95
+
96
+ <label class="addElementLabel">Low Hip:</label>
97
+ <input type="text" id="lowHip" name="lowHip" th:value="${actor.lowHip}" class="formInput">
98
+ <br><br>
99
+
100
+ <label class="addElementLabel">Armseye to Armseye (Front):</label>
101
+ <input type="text" id="armseyeToArmseyeFront" name="armseyeToArmseyeFront"
102
+ th:value="${actor.armseyeToArmseyeFront}" class="formInput">
103
+ <br><br>
104
+
105
+ <label class="addElementLabel">Neck to Waist (Front):</label>
106
+ <input type="text" id="neckToWaistFront" name="neckToWaistFront" th:value="${actor.neckToWaistFront}"
107
+ class="formInput">
108
+ <br><br>
109
+
110
+ <label class="addElementLabel">Armseye to Armseye (Back):</label>
111
+ <input type="text" id="armseyeToArmseyeBack" name="armseyeToArmseyeBack"
112
+ th:value="${actor.armseyeToArmseyeBack}" class="formInput">
113
+ <br><br>
114
+
115
+ <label class="addElementLabel">Neck to Waist (Back):</label>
116
+ <input type="text" id="neckToWaistBack" name="neckToWaistBack" th:value="${actor.neckToWaistBack}"
117
+ class="formInput">
118
+ <br><br>
119
+
120
+ <label class="addElementLabel">Center Back to Wrist:</label>
121
+ <input type="text" id="centerBackToWrist" name="centerBackToWrist" th:value="${actor.centerBackToWrist}"
122
+ class="formInput">
123
+ <br><br>
124
+
125
+ <label class="addElementLabel">Outsleeve to Wrist:</label>
126
+ <input type="text" id="outsleeveToWrist" name="outsleeveToWrist" th:value="${actor.outsleeveToWrist}"
127
+ class="formInput">
128
+ <br><br>
129
+
130
+ <label class="addElementLabel">Outseam (Below Knee):</label>
131
+ <input type="text" id="outseamBelowKnee" name="outseamBelowKnee" th:value="${actor.outseamBelowKnee}"
132
+ class="formInput">
133
+ <br><br>
134
+
135
+ <label class="addElementLabel">Outseam to Ankle:</label>
136
+ <input type="text" id="outseamToAnkle" name="outseamToAnkle" th:value="${actor.outseamToAnkle}"
137
+ class="formInput">
138
+ <br><br>
139
+
140
+ <label class="addElementLabel">Outseam to Floor:</label>
141
+ <input type="text" id="outseamToFloor" name="outseamToFloor" th:value="${actor.outseamToFloor}"
142
+ class="formInput">
143
+ <br><br>
144
+
145
+
146
+ <label class="addElementLabel">Other Notes:</label>
147
+ <input type="text" id="otherNotes" name="otherNotes" th:value="${actor.otherNotes}" class="formInput">
148
+ <br><br>
149
+
150
+ <button type="button" onclick="editActor('${actor.netID}')" class="basicButton">Edit Actor</button>
151
+ </form>
152
+
153
+ </body>
src/main/resources/templates/characters/addCharacters.html ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title>Creighton Theater Database</title>
6
+ <link rel="stylesheet" href="/style.css">
7
+ <script src="/characterScript.js"></script>
8
+ <script src="/script.js"></script>
9
+ </head>
10
+
11
+ <body class="page-background"
12
+ onload="findNetIDFromName('', 'netID', 'Character'); addEventListeners('Character'); addShowEventListeners('Character'); searchByShowAtt('showName', '', 'Character')">
13
+
14
+ <button onclick="location.href='/'" class="basicButton">Home</button>
15
+ <button onclick="location.href='/characters/loadpage'" class="basicButton"
16
+ style="font-size: smaller; margin-bottom: var(--space-md);">Back to Character List</button>
17
+
18
+ <h1 style="text-align: center;">ADD CHARACTER PAGE</h1>
19
+
20
+ <form id="add-character-form">
21
+
22
+ <div class="input-with-button">
23
+ <label for="netID" class="addElementLabel">NetID:</label>
24
+ <input type="text" id="netIDInput" name="netID" class="formInput" required>
25
+ <button type="button" class="square-button"
26
+ onclick="clearInput('netIDInput'); clearInput('firstName'); clearInput('lastName'); findNetIDFromName('', 'netID', 'Character');">×</button>
27
+ </div>
28
+
29
+
30
+ <label for="firstName" class="addElementLabel">First Name:</label>
31
+ <input type="text" id="firstName" name="firstName" class="formInput">
32
+
33
+ <label for="lastName" class="addElementLabel">Last Name:</label>
34
+ <input type="text" id="lastName" name="lastName" class="formInput">
35
+
36
+ <div style="text-align: center;">
37
+ <select size="5" id="student-select" onclick="addSetNetID(this, 'Character')" class="table-select"></select>
38
+ <option value="netID"></option>
39
+ </div>
40
+
41
+
42
+ <label for="characterName" class="addElementLabel">Character Name:</label>
43
+ <input type="text" id="characterName" name="characterName" class="formInput" required>
44
+ <br><br>
45
+
46
+ <div class="input-with-button">
47
+ <label for="showName" class="addElementLabel">Show Name:</label>
48
+ <input type="text" id="showName" name="showName" class="formInput" required>
49
+ <button type="button" class="square-button"
50
+ onclick="clearInput('showName'); clearInput('yearSemester'); searchByShowAtt('showName', '', 'Character')">x</button>
51
+ </div>
52
+ <br><br>
53
+
54
+ <label for="yearSemester" class="addElementLabel">Year Semester (e.g., 'Fall 2023'):</label>
55
+ <input type="text" id="yearSemester" name="yearSemester" class="formInput" required>
56
+ <br><br>
57
+
58
+ <p hidden id = "showID"></p>
59
+
60
+ <div style="text-align: center;">
61
+ <select size="4" id="show-select" onclick="addSetShow(this, 'Character')"
62
+ class="table-select"></select>
63
+ <option value="showID"></option>
64
+ </div>
65
+
66
+
67
+ <button type="button" onclick="addCharacter()" class="basicButton" id="addCharacterButton">
68
+ Add Character
69
+ </button>
70
+
71
+
72
+ </form>
73
+ </body>
src/main/resources/templates/characters/character.html ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title>Creighton Theater Database</title>
6
+ <link rel="stylesheet" href="/style.css">
7
+ <script src="/characterScript.js"></script>
8
+ <script src="/script.js"></script>
9
+
10
+ </head>
11
+
12
+ <body onload = " populateFilterDropdown(); loadCharacters(); processFilter();" class ="page-background">
13
+
14
+ <button onclick="location.href='/'" class="basicButton">Home</button>
15
+ <h1 style="text-align: center;">CHARACTERS PAGE</h1>
16
+ <input type="text" placeholder="Search by NetID" id="filter-input" class="search-bar">
17
+ <select id="filter-column" onchange="clearInput('filter-input'); processFilter(); updatePlaceholder();" class="filter-select" value="netID,c"></select>
18
+ <button onclick="location.href='/characters/addpage'" style = "float: right;" class = "basicButton">Add Character</button>
19
+
20
+ <table>
21
+ <thead>
22
+ <tr>
23
+ <th>Character Name</th>
24
+ <th>Show Name</th>
25
+ <th>Show Semester</th>
26
+ <th>Student Name</th>
27
+ <th>NetID</th>
28
+ <th>Show ID</th>
29
+ </tr>
30
+ </thead>
31
+ <tbody id="character-table-body">
32
+ </tbody>
33
+ </table>
34
+
35
+ <script>
36
+ //dynamically updates the page as the user types into filter-input
37
+ const filterInput = document.getElementById("filter-input");
38
+ filterInput.addEventListener("input", () => {
39
+ processFilter();
40
+ });</script>
41
+ </body>
src/main/resources/templates/crew/addCrew.html ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <head>
3
+ <meta charset="UTF-8">
4
+ <title>Creighton Theater Database</title>
5
+ <link rel="stylesheet" href="/style.css">
6
+ <script src="/crewScript.js"></script>
7
+ <script src = "/script.js"></script>
8
+ </head>
9
+
10
+ <body class="page-background" onload="findNetIDFromName('', 'netID', 'Crew'); addEventListeners('Crew');">
11
+
12
+ <button onclick="location.href='/'" class="basicButton">Home</button>
13
+ <button onclick="location.href='/crew/loadpage'" class="basicButton"
14
+ style="font-size: smaller; margin-bottom: var(--space-md);">Back to Crew List</button>
15
+
16
+ <h1 style="text-align: center;">ADD CREW PAGE</h1>
17
+
18
+ <form id="add-crew-form">
19
+ <div class="input-with-button">
20
+ <label for="netID" class="addElementLabel">NetID:</label>
21
+ <input type="text" id="netIDInput" name="netID" class="formInput" required>
22
+ <button type="button" class="square-button"
23
+ onclick="clearInput('netIDInput'); clearInput('firstName'); clearInput('lastName'); findNetIDFromName('', 'netID', 'Crew');">×</button>
24
+ </div>
25
+
26
+
27
+ <label for="firstName" class="addElementLabel">First Name:</label>
28
+ <input type="text" id="firstName" name="firstName" class="formInput">
29
+
30
+ <label for="lastName" class="addElementLabel">Last Name:</label>
31
+ <input type="text" id="lastName" name="lastName" class="formInput">
32
+
33
+ <div style="text-align: center;">
34
+ <select size="5" id="student-select" onclick="addSetNetID(this, 'Crew')"></select>
35
+ <option value="netID"></option>
36
+ </div>
37
+
38
+ <label for="wigTrained" class="addElementLabel">Wig Trained(Check if yes):</label>
39
+ <input type="checkbox" id="wigTrained" name="wigTrained" value="1" class="checkBox">
40
+ <br><br>
41
+
42
+ <label for="makeupTrained" class="addElementLabel">Makeup Trained(Check if yes):</label>
43
+ <input type="checkbox" id="makeupTrained" name="makeupTrained" value = "1" class="checkBox">
44
+ <br><br>
45
+
46
+ <label for="musicReading" class="addElementLabel">Music Reading(Check if yes):</label>
47
+ <input type="checkbox" id="musicReading" name="musicReading" value = "1"class="checkBox">
48
+ <br><br>
49
+
50
+ <label for="lighting" class="addElementLabel">Lighting Training(Describe):</label>
51
+ <input type="text" id="lighting" name="lighting" class="formInput">
52
+
53
+ <label for="sound" class="addElementLabel">Sound Training(Describe):</label>
54
+ <input type="text" id="sound" name="sound" class="formInput">
55
+
56
+ <label for="specialty" class="addElementLabel">Specialty:</label>
57
+ <input type="text" id="specialty" name="specialty" class="formInput">
58
+
59
+ <label for="notes" class="addElementLabel">Notes:</label>
60
+ <input type="text" id="notes" name="notes" class="formInput">
61
+
62
+
63
+ <button type="button" onclick="addCrew()" class="basicButton" id = "addCrewButton">
64
+ Add Crew
65
+ </button>
66
+
67
+ </form>
68
+
69
+
70
+ </body>
src/main/resources/templates/crew/crew.html ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title>Creighton Theater Database</title>
6
+ <link rel="stylesheet" href="/style.css">
7
+ <script src="/crewScript.js"></script>
8
+ </head>
9
+
10
+ <body onload="loadCrew();" class="page-background">
11
+ <button onclick="location.href='/'" class="basicButton">Home</button>
12
+ <h1 style="text-align: center;">Crew Page</h1>
13
+ <button onclick="location.href='/crew/add'" class="basicButton" style = "float: right;">Add New Crew</button>
14
+ <label for ="filter-input" style="margin-right: 10px;">Filter By NetID:</label>
15
+ <input type="text" placeholder="Search by NetID" id="filter-input" class="search-bar">
16
+
17
+ <div class="wide-table-container">
18
+ <table class="styled-table" style="border-collapse:collapse">
19
+ <thead>
20
+ <tr>
21
+ <th>NetID</th>
22
+ <th class = "sticky">Name</th>
23
+ <th>Wig Trained</th>
24
+ <th>Makeup Trained</th>
25
+ <th>Music Reading</th>
26
+ <th>Lighting</th>
27
+ <th>Sound</th>
28
+ <th>Specialty</th>
29
+ <th>Notes</th>
30
+
31
+
32
+ </tr>
33
+ </thead>
34
+ <tbody id="crew-table-body">
35
+ </tbody>
36
+ </table>
37
+ </div>
38
+ <script>
39
+ //dynamically updates the page as the user types into filter-input
40
+ const filterInput = document.getElementById("filter-input");
41
+ filterInput.addEventListener("input", () => {
42
+ processFilter();
43
+ });</script>
44
+
45
+
46
+ </body>
src/main/resources/templates/help.html ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <p>The interface should be pretty intuitive. Previous shows is not yet implemented for Students.
2
+ show search function is not yet implemented.
3
+
4
+ Also, I've connected the create and insert files sql files for the databsae,
5
+ you are probably going to have to change the user and password in application.properties
6
+ (src/main/resources/application.properties).
7
+
8
+ Also, if terminal launch doesn't work, then go to TheaterDatabaseApplication.java and just press run (if using
9
+ vsCode).
10
+
11
+ I know the launch/setup might be a little janky, so if you have any questions just email me.</p>
src/main/resources/templates/index.html ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <head>
2
+ <meta charset="UTF-8">
3
+ <title>Creighton Theater Database</title>
4
+ <link rel="stylesheet" href="/style.css">
5
+ <script src="/script.js"></script>
6
+ </head>
7
+
8
+ <body class="page-background">
9
+ <h1 style="font-size: 40px">Welcome to Creighton Theater Database</h1>
10
+ <div class="buttons-container">
11
+
12
+ <button class="home-buttons" onclick="location.href='/help'">Help</button>
13
+ <button class="home-buttons" onclick="location.href='/student/loadpage'">VIEW STUDENTS</button>
14
+ <button class="home-buttons" onclick="location.href='/actors/loadpage'">VIEW ACTORS</button>
15
+ <button class="home-buttons" onclick="location.href='/crew/loadpage'">VIEW CREW</button>
16
+ <button class="home-buttons" onclick="location.href='/show/loadpage'">VIEW SHOWS</button>
17
+ <button class="home-buttons" onclick="location.href='/characters/loadpage'">VIEW CHARACTERS</button>
18
+ </div>
19
+
20
+ </body>
src/main/resources/templates/shows/shows.html ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title>Creighton Theater Database</title>
6
+ <link rel="stylesheet" href="/style.css">
7
+ <script src="/showScript.js"></script>
8
+ <script src="/script.js"></script>
9
+ </head>
10
+
11
+ <body onload="loadShows();" class="page-background">
12
+ <button onclick="location.href='/'" class="basicButton">Home</button>
13
+ <h1 style="text-align: center;">Show Page</h1>
14
+ <label for ="filter-input" style="margin-right: 10px;">Filter By Net ID:</label>
15
+ <input type="text" placeholder="Search by NetID" id="filter-input" class="search-bar">
16
+
17
+ <table class="styled-table">
18
+ <thead>
19
+
20
+
21
+ <th>Show ID</th>
22
+ <th >Show Name</th>
23
+ <th>Year/Semester</th>
24
+ <th>Director</th>
25
+ <th>Genre</th>
26
+ <th>Playwright</th>
27
+
28
+ </tr>
29
+ </thead>
30
+ <tbody id="show-table-body">
31
+ </tbody>
32
+ </table>
33
+
34
+ </body>
src/main/resources/templates/student/addStudents.html ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title>Creighton Theater Database</title>
6
+ <link rel="stylesheet" href="/style.css">
7
+ <script src="/studentScript.js"> </script>
8
+ </head>
9
+
10
+ <body class="page-background" onload = "validateNetID()" >
11
+
12
+ <button onclick="location.href='/'" class="basicButton">Home</button>
13
+ <button onclick="location.href='/student/loadpage'" class="basicButton" style = "font-size: smaller; margin-bottom: var(--space-md);">Back to Student List</button>
14
+ <h1 style="text-align: center;">ADD STUDENT PAGE</h1>
15
+
16
+ <form id="add-student-form">
17
+ <label for="netId" class="addElementLabel">NetID:</label>
18
+ <input type="text" id="netID" name="netID"required>
19
+ <br><br>
20
+
21
+ <label for="firstName" class="addElementLabel">First Name:</label>
22
+ <input type="text" id="firstName" name="firstName" required><br><br>
23
+
24
+ <label for="lastName" class="addElementLabel">Last Name:</label>
25
+ <input type="text" id="lastName" name="lastName" required><br><br>
26
+
27
+ <label for="grade" class="addElementLabel">Grade:</label>
28
+ <input type="text" id="gradeLevel" name="gradeLevel" required><br><br>
29
+
30
+ <label for="pronouns" class="addElementLabel">Pronouns:</label>
31
+ <input type="text" id="pronouns" name="pronouns"><br><br>
32
+
33
+ <label for="specialNotes" class="addElementLabel">Special Notes:</label>
34
+ <input type="text" id="specialNotes" name="specialNotes"><br><br>
35
+
36
+ <label for="email" class="addElementLabel">Email:</label>
37
+ <input type="email" id="email" name="email"><br><br>
38
+
39
+ <label for="allergies" class="addElementLabel">Allergies/Sensitivities:</label>
40
+ <input type="text" id="allergies" name="allergies_sensitivities"><br><br>
41
+
42
+ <button type="button" onclick = "addStudent()" class = "basicButton">Add Student</button>
43
+ </form>
44
+
45
+
src/main/resources/templates/student/editStudents.html ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title>Creighton Theater Database</title>
6
+ <link rel="stylesheet" href="/style.css">
7
+ <script src="/studentScript.js"> </script>
8
+
9
+ </head>
10
+
11
+ <body class="page-background">
12
+
13
+ <button onclick="location.href='/'" class="basicButton">Home</button>
14
+ <button onclick="location.href='/student/loadpage'" class="basicButton"
15
+ style="font-size: smaller; margin-bottom: var(--space-md);">Back to Student List</button>
16
+ <h1 style="text-align: center;">EDIT STUDENT PAGE</h1>
17
+
18
+ <form id="edit-student-form">
19
+ <label for="netId" class="addElementLabel">NetID:</label>
20
+ <input type="text" id="netID" name="netID" required style="align-items:center;" th:value="${student.netID}" class="formInput">
21
+ <br><br>
22
+
23
+ <label for="firstName" class="addElementLabel">First Name:</label>
24
+ <input type="text" id="firstName" name="firstName" required th:value="${student.firstName}" class="formInput"><br><br>
25
+
26
+ <label for="lastName" class="addElementLabel">Last Name:</label>
27
+ <input type="text" id="lastName" name="lastName" required th:value="${student.lastName}" class="formInput"><br><br>
28
+
29
+ <label for="grade" class="addElementLabel">Grade:</label>
30
+ <input type="text" id="gradeLevel" name="gradeLevel" required th:value="${student.gradeLevel}" class="formInput"><br><br>
31
+
32
+ <label for="pronouns" class="addElementLabel">Pronouns:</label>
33
+ <input type="text" id="pronouns" name="pronouns" th:value="${student.pronouns}" class="formInput"><br><br>
34
+
35
+ <label for="specialNotes" class="addElementLabel">Special Notes:</label>
36
+ <input type="text" id="specialNotes" name="specialNotes" th:value="${student.specialNotes}" class="formInput"><br><br>
37
+
38
+ <label for="email" class="addElementLabel">Email:</label>
39
+ <input type="email" id="email" name="email" th:value="${student.email}" class="formInput"><br><br>
40
+
41
+ <label for="allergies" class="addElementLabel">Allergies/Sensitivities:</label>
42
+ <input type="text" id="allergies" name="allergies_sensitivities"th:value="${student.allergies_sensitivities}" class="formInput"><br><br>
43
+
44
+ <button type="button" onclick="editStudent('${student.netID}')" class="basicButton">Edit Student</button>
45
+ </form>
46
+ <script>
47
+
48
+ </script>
49
+ </body>
src/main/resources/templates/student/students.html ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title>Creighton Theater Database</title>
6
+ <link rel="stylesheet" href="/style.css">
7
+ <script src="/studentScript.js"> </script>
8
+ <script src = "/script.js"></script>
9
+ </head>
10
+
11
+ <body onload = "loadStudents(), populateFilterDropdown()" class ="page-background">
12
+
13
+ <button onclick="location.href='/'" class="basicButton">Home</button>
14
+ <h1 style="text-align: center;">STUDENTS PAGE</h1>
15
+ <input type="text" placeholder="Search by NetID" id="filter-input" class="search-bar">
16
+ <select id="filter-column" onchange="clearInput('filter-input'); loadStudents(); updatePlaceholder();" class="filter-select"></select>
17
+
18
+ <button onclick="location.href='/addStudent'" style = "float: right;" class = "basicButton">Add Student</button>
19
+
20
+ <table>
21
+ <thead>
22
+ <tr>
23
+ <th>NetID</th>
24
+ <th>Name</th>
25
+ <th>Grade</th>
26
+ <th>Pronouns</th>
27
+ <th>Special Notes</th>
28
+ <th>Email</th>
29
+ <th>Allergies/Sensitivities</th>
30
+ </tr>
31
+ </thead>
32
+ <tbody id="student-table-body">
33
+ </tbody>
34
+ </table>
35
+
36
+ <script>
37
+ //dynamically updates the page as the user types into filter-input
38
+ const filterInput = document.getElementById("filter-input");
39
+ filterInput.addEventListener("input", () => {
40
+ processFilter("student");
41
+ });</script>
42
+ </body>
src/main/todo.txt ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ -fix editStudent page (netID so that it updates across all tables)
2
+ -Fix delete student so that it fixes all foreign key references as well
3
+
4
+ -When you search, you still need the select on netID
5
+ -edit actor
6
+ -delete actor
7
+ -edit crew
8
+ -delete crew
9
+ -delete character
10
+ -Actors and crew and character page for shows
11
+ -Find out how to add photo file
12
+ -figure out non-student for crew
13
+
14
+ - dressing list for character
15
+ -clothing, accessories, laundry instructions
16
+ -Make it so that you can copy characters to new shows
17
+ -Show dressing list for actor/character
18
+ -If actor connected to multiple characters
19
+ -Connect to costume database
20
+ -could be one costume assigned to multiple characters
21
+ -Add ability to go to actor from actor
src/test/java/com/creighton_theater/theater_database/TheaterDatabaseApplicationTests.java ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package com.creighton_theater.theater_database;
2
+
3
+ import org.junit.jupiter.api.Test;
4
+ import org.springframework.boot.test.context.SpringBootTest;
5
+
6
+ @SpringBootTest
7
+ class TheaterDatabaseApplicationTests {
8
+
9
+ @Test
10
+ void contextLoads() {
11
+ }
12
+
13
+ }