From e98feaf3b57dfea34d9aef040f5447a7dc469d00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Minelli?= <michael@minelli.me> Date: Tue, 12 Sep 2023 19:19:38 +0200 Subject: [PATCH] Rename enonce and exercice to assignment and exercise --- .gitlab-ci.yml | 88 ++++++++++------- NodeApp/package.json | 2 +- NodeApp/src/commander/CommanderApp.ts | 10 +- .../commander/assignment/AssignmentCommand.ts | 25 +++++ .../AssignmentCreateCommand.ts} | 32 +++---- .../assignment/AssignmentPublishCommand.ts | 10 ++ .../AssignmentPublishUnpublishCommandBase.ts | 83 ++++++++++++++++ .../assignment/AssignmentUnpublishCommand.ts | 10 ++ NodeApp/src/commander/enonce/EnonceCommand.ts | 25 ----- .../commander/enonce/EnoncePublishCommand.ts | 10 -- .../EnoncePublishUnpublishCommandBase.ts | 83 ---------------- .../enonce/EnonceUnpublishCommand.ts | 10 -- .../src/commander/exercice/ExerciceCommand.ts | 23 ----- .../exercice/ExerciceCreateCommand.ts | 91 ------------------ .../src/commander/exercise/ExerciseCommand.ts | 23 +++++ .../exercise/ExerciseCreateCommand.ts | 91 ++++++++++++++++++ .../ExerciseRunCommand.ts} | 94 +++++++++---------- NodeApp/src/config/Config.ts | 16 ++-- NodeApp/src/managers/DojoBackendManager.ts | 54 +++++------ 19 files changed, 400 insertions(+), 380 deletions(-) create mode 100644 NodeApp/src/commander/assignment/AssignmentCommand.ts rename NodeApp/src/commander/{enonce/EnonceCreateCommand.ts => assignment/AssignmentCreateCommand.ts} (65%) create mode 100644 NodeApp/src/commander/assignment/AssignmentPublishCommand.ts create mode 100644 NodeApp/src/commander/assignment/AssignmentPublishUnpublishCommandBase.ts create mode 100644 NodeApp/src/commander/assignment/AssignmentUnpublishCommand.ts delete mode 100644 NodeApp/src/commander/enonce/EnonceCommand.ts delete mode 100644 NodeApp/src/commander/enonce/EnoncePublishCommand.ts delete mode 100644 NodeApp/src/commander/enonce/EnoncePublishUnpublishCommandBase.ts delete mode 100644 NodeApp/src/commander/enonce/EnonceUnpublishCommand.ts delete mode 100644 NodeApp/src/commander/exercice/ExerciceCommand.ts delete mode 100644 NodeApp/src/commander/exercice/ExerciceCreateCommand.ts create mode 100644 NodeApp/src/commander/exercise/ExerciseCommand.ts create mode 100644 NodeApp/src/commander/exercise/ExerciseCreateCommand.ts rename NodeApp/src/commander/{exercice/ExerciceRunCommand.ts => exercise/ExerciseRunCommand.ts} (66%) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 1592254..4c0541b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,62 +1,82 @@ variables: BIN_FOLDER: /binary BIN_NAME: dojo + CLI_PROJECT_FOLDER: NodeApp + GIT_SUBMODULE_STRATEGY: recursive + GIT_SUBMODULE_FORCE_HTTPS: "true" + SECURE_FILES_DOWNLOAD_PATH: './' -.macOS-sign_and_pkg: +.build_cli: + script: + - cd NodeApp + # Download secure files + - curl --silent "https://gitlab.com/gitlab-org/incubation-engineering/mobile-devops/download-secure-files/-/raw/main/installer" | bash + - mv env_$VERSION .env + # Install dependencies + - npm install + - npm run build + # Build binaries + - npx pkg . -t node18-macos-arm64 --output $BIN_FOLDER/macOS/arm64/$BIN_NAME --no-bytecode --public-packages "*" --public + - npx pkg . -t node18-macos-x64 --output $BIN_FOLDER/macOS/x64/$BIN_NAME --no-bytecode --public-packages "*" --public + - npx pkg . -t node18-linuxstatic-arm64 --output $BIN_FOLDER/linux/arm64/$BIN_NAME --no-bytecode --public-packages "*" --public + - npx pkg . -t node18-linuxstatic-x64 --output $BIN_FOLDER/linux/x64/$BIN_NAME --no-bytecode --public-packages "*" --public + - npx pkg . -t node18-win-arm64 --output $BIN_FOLDER/Windows/arm64/$BIN_NAME --no-bytecode --public-packages "*" --public + - npx pkg . -t node18-win-x64 --output $BIN_FOLDER/Windows/x64/$BIN_NAME --no-bytecode --public-packages "*" --public + +.macos-sign_and_pkg: script: # Sign excecutable - - codesign --force --options=runtime --entitlements ../../../Resources/macApp/Signing/entitlements.plist --sign $SIGN_DEV_ID_APP --keychain $SIGN_LOGIN_KEYCHAIN_PATH --timestamp ${BIN_NAME} + - codesign --force --options=runtime --entitlements ../../../Resources/macApp/Signing/entitlements.plist --sign $SIGN_DEV_ID_APP --keychain $SIGN_LOGIN_KEYCHAIN_PATH --timestamp ${BIN_NAME} # Package and notarize the app - xcrun notarytool store-credentials --apple-id $SIGN_APPLE_ID --team-id $SIGN_TEAM_ID --password $SIGN_APP_PASSWORD --keychain $SIGN_LOGIN_KEYCHAIN_PATH $SIGN_KEYCHAIN_PROFILE - ditto ${BIN_NAME} ${BIN_NAME}_pkg/usr/local/bin/ - - productbuild --identifier $SIGN_IDENTIFIER --version $APP_VERSION --sign $SIGN_DEV_ID_INST --keychain $SIGN_LOGIN_KEYCHAIN_PATH --timestamp --root ${BIN_NAME}_pkg / ${BIN_NAME}.pkg + - productbuild --identifier $SIGN_IDENTIFIER --version $APP_VERSION --sign $SIGN_DEV_ID_INST --keychain $SIGN_LOGIN_KEYCHAIN_PATH --timestamp --root ${BIN_NAME}_pkg / ${BIN_NAME}.pkg - xcrun notarytool submit ${BIN_NAME}.pkg --keychain $SIGN_LOGIN_KEYCHAIN_PATH --keychain-profile $SIGN_KEYCHAIN_PROFILE --wait - xcrun stapler staple ${BIN_NAME}.pkg #Clean folder - rm -Rf ${BIN_NAME}_pkg +stages: + - build + - sign -image: node:latest - -cache: - paths: - - NodeApp/node_modules/ +default: + image: node:latest + cache: + paths: + - $CLI_PROJECT_FOLDER/node_modules/ + before_script: + - apt update + - apt install -y jq + - > + VERSION=$(jq -r .version $CLI_PROJECT_FOLDER/package.json) -stages: - - Build_stage - - Sign_stage +test:build: + stage: build + tags: + - build + script: + - !reference [.build_cli, script] + rules: + - if: '$CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH && $CI_COMMIT_BRANCH !~ /^v[0-9]+(\.[0-9]+)*$/' -build: - stage: Build_stage +deploy:build: + stage: build tags: - build - variables: - GIT_SUBMODULE_STRATEGY: recursive - GIT_SUBMODULE_FORCE_HTTPS: "true" - SECURE_FILES_DOWNLOAD_PATH: './' script: - - cd NodeApp - # Download secure files - - curl --silent "https://gitlab.com/gitlab-org/incubation-engineering/mobile-devops/download-secure-files/-/raw/main/installer" | bash - - mv env .env - # Install dependencies - - npm install - - npm run build - # Build binaries - - npx pkg . -t node18-macos-arm64 --output $BIN_FOLDER/macOS/arm64/$BIN_NAME --no-bytecode --public-packages "*" --public - - npx pkg . -t node18-macos-x64 --output $BIN_FOLDER/macOS/x64/$BIN_NAME --no-bytecode --public-packages "*" --public - - npx pkg . -t node18-linuxstatic-arm64 --output $BIN_FOLDER/linux/arm64/$BIN_NAME --no-bytecode --public-packages "*" --public - - npx pkg . -t node18-linuxstatic-x64 --output $BIN_FOLDER/linux/x64/$BIN_NAME --no-bytecode --public-packages "*" --public - - npx pkg . -t node18-win-arm64 --output $BIN_FOLDER/Windows/arm64/$BIN_NAME --no-bytecode --public-packages "*" --public - - npx pkg . -t node18-win-x64 --output $BIN_FOLDER/Windows/x64/$BIN_NAME --no-bytecode --public-packages "*" --public + - !reference [.build_cli, script] artifacts: untracked: true paths: - $BIN_FOLDER/* expire_in: 1 hour + rules: + - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH || $CI_COMMIT_BRANCH =~ /^v[0-9]+(\.[0-9]+)*$/' sign_macos: - stage: Sign_stage + stage: sign + needs: ["deploy:build"] tags: - macos_signing dependencies: @@ -64,9 +84,9 @@ sign_macos: script: - security unlock-keychain -p $SIGN_KEYCHAIN_PASSWORD $SIGN_LOGIN_KEYCHAIN_PATH - cd $BIN_FOLDER/macOS/arm64 - - !reference [.macOS-sign_and_pkg, script] + - !reference [.macos-sign_and_pkg, script] - cd $BIN_FOLDER/macOS/x64 - - !reference [.macOS-sign_and_pkg, script] + - !reference [.macos-sign_and_pkg, script] artifacts: paths: - $BIN_FOLDER/* diff --git a/NodeApp/package.json b/NodeApp/package.json index 6b739f9..eb09505 100644 --- a/NodeApp/package.json +++ b/NodeApp/package.json @@ -1,6 +1,6 @@ { "name" : "dojo_cli", - "version" : "1.0.1", + "version" : "2.0.0", "main" : "dist/app.js", "bin" : { "dojo": "./dist/app.js" diff --git a/NodeApp/src/commander/CommanderApp.ts b/NodeApp/src/commander/CommanderApp.ts index b374d70..a6002b0 100644 --- a/NodeApp/src/commander/CommanderApp.ts +++ b/NodeApp/src/commander/CommanderApp.ts @@ -1,8 +1,8 @@ import { Command } from 'commander'; -import EnonceCommand from './enonce/EnonceCommand'; import SessionCommand from './session/SessionCommand'; -import ExerciceCommand from './exercice/ExerciceCommand'; import ClientsSharedConfig from '../sharedByClients/config/ClientsSharedConfig'; +import AssignmentCommand from './assignment/AssignmentCommand'; +import ExerciseCommand from './exercise/ExerciseCommand'; class CommanderApp { @@ -12,7 +12,7 @@ class CommanderApp { this.program .name('dojo') .description('CLI of the Dojo application') - .version('1.0.1') + .version('2.0.0') .showHelpAfterError() .configureHelp({ showGlobalOptions: true, @@ -32,8 +32,8 @@ class CommanderApp { private registerCommands() { SessionCommand.registerOnCommand(this.program); - EnonceCommand.registerOnCommand(this.program); - ExerciceCommand.registerOnCommand(this.program); + AssignmentCommand.registerOnCommand(this.program); + ExerciseCommand.registerOnCommand(this.program); } } diff --git a/NodeApp/src/commander/assignment/AssignmentCommand.ts b/NodeApp/src/commander/assignment/AssignmentCommand.ts new file mode 100644 index 0000000..c629ddc --- /dev/null +++ b/NodeApp/src/commander/assignment/AssignmentCommand.ts @@ -0,0 +1,25 @@ +import CommanderCommand from '../CommanderCommand'; +import AssignmentCreateCommand from './AssignmentCreateCommand'; +import AssignmentPublishCommand from './AssignmentPublishCommand'; +import AssignmentUnpublishCommand from './AssignmentUnpublishCommand'; + + +class AssignmentCommand extends CommanderCommand { + protected commandName: string = 'assignment'; + + protected defineCommand() { + this.command + .description('manage an assignment'); + } + + protected defineSubCommands() { + AssignmentCreateCommand.registerOnCommand(this.command); + AssignmentPublishCommand.registerOnCommand(this.command); + AssignmentUnpublishCommand.registerOnCommand(this.command); + } + + protected async commandAction(options: any): Promise<void> { } +} + + +export default new AssignmentCommand(); \ No newline at end of file diff --git a/NodeApp/src/commander/enonce/EnonceCreateCommand.ts b/NodeApp/src/commander/assignment/AssignmentCreateCommand.ts similarity index 65% rename from NodeApp/src/commander/enonce/EnonceCreateCommand.ts rename to NodeApp/src/commander/assignment/AssignmentCreateCommand.ts index 6002d25..c2b384a 100644 --- a/NodeApp/src/commander/enonce/EnonceCreateCommand.ts +++ b/NodeApp/src/commander/assignment/AssignmentCreateCommand.ts @@ -4,18 +4,18 @@ import ora from 'ora'; import GitlabManager from '../../managers/GitlabManager'; import GitlabUser from '../../shared/types/Gitlab/GitlabUser'; import DojoBackendManager from '../../managers/DojoBackendManager'; -import Enonce from '../../sharedByClients/models/Enonce'; import Toolbox from '../../shared/helpers/Toolbox'; import AccessesHelper from '../../helpers/AccessesHelper'; +import Assignment from '../../sharedByClients/models/Assignment'; -class EnonceCreateCommand extends CommanderCommand { +class AssignmentCreateCommand extends CommanderCommand { protected commandName: string = 'create'; protected defineCommand() { this.command - .description('create a new repository for an enonce') - .requiredOption('-n, --name <name>', 'name of the enonce') + .description('create a new repository for an assignment') + .requiredOption('-n, --name <name>', 'name of the assignment') .option('-i, --members_id <ids...>', 'list of gitlab members ids (teaching staff) to add to the repository') .option('-u, --members_username <usernames...>', 'list of gitlab members username (teaching staff) to add to the repository') .option('-t, --template <string>', 'id or url of the template (http/s and ssh urls are possible)') @@ -39,12 +39,12 @@ class EnonceCreateCommand extends CommanderCommand { return; } - const enonceGetSpinner: ora.Ora = ora('Checking enonce name availability').start(); - if ( await DojoBackendManager.getEnonce(options.name) ) { - enonceGetSpinner.fail(`Enonce name "${ options.name }" is already taken. Please choose another one.`); + const assignmentGetSpinner: ora.Ora = ora('Checking assignment name availability').start(); + if ( await DojoBackendManager.getAssignment(options.name) ) { + assignmentGetSpinner.fail(`Assignment name "${ options.name }" is already taken. Please choose another one.`); return; } - enonceGetSpinner.succeed(`Enonce name "${ options.name }" is available`); + assignmentGetSpinner.succeed(`Assignment name "${ options.name }" is available`); if ( options.template ) { templateIdOrNamespace = options.template; @@ -59,12 +59,12 @@ class EnonceCreateCommand extends CommanderCommand { } } - // Create the enonce + // Create the assignment { - console.log(chalk.cyan('Please wait while we are creating the enonce...')); + console.log(chalk.cyan('Please wait while we are creating the assignment...')); try { - const enonce: Enonce = await DojoBackendManager.createEnonce(options.name, members, templateIdOrNamespace); + const assignment: Assignment = await DojoBackendManager.createAssignment(options.name, members, templateIdOrNamespace); const oraInfo = (message: string) => { ora({ @@ -73,10 +73,10 @@ class EnonceCreateCommand extends CommanderCommand { }).start().info(); }; - oraInfo(`${ chalk.magenta('Name:') } ${ enonce.name }`); - oraInfo(`${ chalk.magenta('Web URL:') } ${ enonce.gitlabCreationInfo.web_url }`); - oraInfo(`${ chalk.magenta('HTTP Repo:') } ${ enonce.gitlabCreationInfo.http_url_to_repo }`); - oraInfo(`${ chalk.magenta('SSH Repo:') } ${ enonce.gitlabCreationInfo.ssh_url_to_repo }`); + oraInfo(`${ chalk.magenta('Name:') } ${ assignment.name }`); + oraInfo(`${ chalk.magenta('Web URL:') } ${ assignment.gitlabCreationInfo.web_url }`); + oraInfo(`${ chalk.magenta('HTTP Repo:') } ${ assignment.gitlabCreationInfo.http_url_to_repo }`); + oraInfo(`${ chalk.magenta('SSH Repo:') } ${ assignment.gitlabCreationInfo.ssh_url_to_repo }`); } catch ( error ) { return; } @@ -85,4 +85,4 @@ class EnonceCreateCommand extends CommanderCommand { } -export default new EnonceCreateCommand(); \ No newline at end of file +export default new AssignmentCreateCommand(); \ No newline at end of file diff --git a/NodeApp/src/commander/assignment/AssignmentPublishCommand.ts b/NodeApp/src/commander/assignment/AssignmentPublishCommand.ts new file mode 100644 index 0000000..6816aa3 --- /dev/null +++ b/NodeApp/src/commander/assignment/AssignmentPublishCommand.ts @@ -0,0 +1,10 @@ +import AssignmentPublishUnpublishCommandBase from './AssignmentPublishUnpublishCommandBase'; + + +class AssignmentPublishCommand extends AssignmentPublishUnpublishCommandBase { + protected commandName: string = 'publish'; + protected publish: boolean = true; +} + + +export default new AssignmentPublishCommand(); \ No newline at end of file diff --git a/NodeApp/src/commander/assignment/AssignmentPublishUnpublishCommandBase.ts b/NodeApp/src/commander/assignment/AssignmentPublishUnpublishCommandBase.ts new file mode 100644 index 0000000..b5df0c9 --- /dev/null +++ b/NodeApp/src/commander/assignment/AssignmentPublishUnpublishCommandBase.ts @@ -0,0 +1,83 @@ +import CommanderCommand from '../CommanderCommand'; +import inquirer from 'inquirer'; +import chalk from 'chalk'; +import SessionManager from '../../managers/SessionManager'; +import ora from 'ora'; +import DojoBackendManager from '../../managers/DojoBackendManager'; +import Assignment from '../../sharedByClients/models/Assignment'; + + +abstract class AssignmentPublishUnpublishCommandBase extends CommanderCommand { + protected abstract publish: boolean; + + protected defineCommand() { + this.command + .description('publish an assignment') + .argument('<name or url>', 'name or url (http/s or ssh) of the assignment') + .option('-f, --force', 'don\'t ask for confirmation') + .action(this.commandAction.bind(this)); + } + + protected async commandAction(assignmentNameOrUrl: string, options: { force: boolean }): Promise<void> { + if ( !options.force ) { + options.force = (await inquirer.prompt({ + type : 'confirm', + name : 'force', + message: this.publish ? 'Are you sure you want to publish this assignment?' : 'Are you sure you want to unpublish this assignment?' + })).force; + } + + if ( !options.force ) { + return; + } + + let assignment!: Assignment | undefined; + + { + console.log(chalk.cyan('Please wait while we verify and retrieve data...')); + + if ( !await SessionManager.testSession(true, null) ) { + return; + } + + ora('Checking assignment:').start().info(); + ora({ + text : assignmentNameOrUrl, + indent: 4 + }).start().info(); + const assignmentGetSpinner: ora.Ora = ora({ + text : 'Checking if assignment exists', + indent: 8 + }).start(); + assignment = await DojoBackendManager.getAssignment(assignmentNameOrUrl); + if ( !assignment ) { + assignmentGetSpinner.fail(`The assignment doesn't exists`); + return; + } + assignmentGetSpinner.succeed(`The assignment exists`); + + const assignmentCheckAccessSpinner: ora.Ora = ora({ + text : 'Checking accesses', + indent: 8 + }).start(); + if ( !assignment.staff ) { + assignmentCheckAccessSpinner.fail(`You are not in the staff of this assignment`); + return; + } + assignmentCheckAccessSpinner.succeed(`You are in the staff of this assignment`); + } + + { + console.log(chalk.cyan(`Please wait while we ${ this.publish ? 'publish' : 'unpublish' } the assignment...`)); + + try { + await DojoBackendManager.changeAssignmentPublishedStatus(assignment, this.publish); + } catch ( error ) { + return; + } + } + } +} + + +export default AssignmentPublishUnpublishCommandBase; \ No newline at end of file diff --git a/NodeApp/src/commander/assignment/AssignmentUnpublishCommand.ts b/NodeApp/src/commander/assignment/AssignmentUnpublishCommand.ts new file mode 100644 index 0000000..e329c48 --- /dev/null +++ b/NodeApp/src/commander/assignment/AssignmentUnpublishCommand.ts @@ -0,0 +1,10 @@ +import AssignmentPublishUnpublishCommandBase from './AssignmentPublishUnpublishCommandBase'; + + +class AssignmentUnpublishCommand extends AssignmentPublishUnpublishCommandBase { + protected commandName: string = 'unpublish'; + protected publish: boolean = false; +} + + +export default new AssignmentUnpublishCommand(); \ No newline at end of file diff --git a/NodeApp/src/commander/enonce/EnonceCommand.ts b/NodeApp/src/commander/enonce/EnonceCommand.ts deleted file mode 100644 index dc3a5f3..0000000 --- a/NodeApp/src/commander/enonce/EnonceCommand.ts +++ /dev/null @@ -1,25 +0,0 @@ -import CommanderCommand from '../CommanderCommand'; -import EnonceCreateCommand from './EnonceCreateCommand'; -import EnoncePublishCommand from './EnoncePublishCommand'; -import EnonceUnpublishCommand from './EnonceUnpublishCommand'; - - -class EnonceCommand extends CommanderCommand { - protected commandName: string = 'enonce'; - - protected defineCommand() { - this.command - .description('manage an enonce'); - } - - protected defineSubCommands() { - EnonceCreateCommand.registerOnCommand(this.command); - EnoncePublishCommand.registerOnCommand(this.command); - EnonceUnpublishCommand.registerOnCommand(this.command); - } - - protected async commandAction(options: any): Promise<void> { } -} - - -export default new EnonceCommand(); \ No newline at end of file diff --git a/NodeApp/src/commander/enonce/EnoncePublishCommand.ts b/NodeApp/src/commander/enonce/EnoncePublishCommand.ts deleted file mode 100644 index 91900f6..0000000 --- a/NodeApp/src/commander/enonce/EnoncePublishCommand.ts +++ /dev/null @@ -1,10 +0,0 @@ -import EnoncePublishUnpublishCommandBase from './EnoncePublishUnpublishCommandBase'; - - -class EnoncePublishCommand extends EnoncePublishUnpublishCommandBase { - protected commandName: string = 'publish'; - protected publish: boolean = true; -} - - -export default new EnoncePublishCommand(); \ No newline at end of file diff --git a/NodeApp/src/commander/enonce/EnoncePublishUnpublishCommandBase.ts b/NodeApp/src/commander/enonce/EnoncePublishUnpublishCommandBase.ts deleted file mode 100644 index c94c419..0000000 --- a/NodeApp/src/commander/enonce/EnoncePublishUnpublishCommandBase.ts +++ /dev/null @@ -1,83 +0,0 @@ -import CommanderCommand from '../CommanderCommand'; -import inquirer from 'inquirer'; -import Enonce from '../../sharedByClients/models/Enonce'; -import chalk from 'chalk'; -import SessionManager from '../../managers/SessionManager'; -import ora from 'ora'; -import DojoBackendManager from '../../managers/DojoBackendManager'; - - -abstract class EnoncePublishUnpublishCommandBase extends CommanderCommand { - protected abstract publish: boolean; - - protected defineCommand() { - this.command - .description('publish an enonce') - .argument('<name or url>', 'name or url (http/s or ssh) of the enonce') - .option('-f, --force', 'don\'t ask for confirmation') - .action(this.commandAction.bind(this)); - } - - protected async commandAction(enonceNameOrUrl: string, options: { force: boolean }): Promise<void> { - if ( !options.force ) { - options.force = (await inquirer.prompt({ - type : 'confirm', - name : 'force', - message: this.publish ? 'Are you sure you want to publish this enonce?' : 'Are you sure you want to unpublish this enonce?' - })).force; - } - - if ( !options.force ) { - return; - } - - let enonce!: Enonce | undefined; - - { - console.log(chalk.cyan('Please wait while we verify and retrieve data...')); - - if ( !await SessionManager.testSession(true, null) ) { - return; - } - - ora('Checking enonce:').start().info(); - ora({ - text : enonceNameOrUrl, - indent: 4 - }).start().info(); - const enonceGetSpinner: ora.Ora = ora({ - text : 'Checking if enonce exists', - indent: 8 - }).start(); - enonce = await DojoBackendManager.getEnonce(enonceNameOrUrl); - if ( !enonce ) { - enonceGetSpinner.fail(`The enonce doesn't exists`); - return; - } - enonceGetSpinner.succeed(`The enonce exists`); - - const enonceCheckAccessSpinner: ora.Ora = ora({ - text : 'Checking accesses', - indent: 8 - }).start(); - if ( !enonce.staff ) { - enonceCheckAccessSpinner.fail(`You are not in the staff of this enonce`); - return; - } - enonceCheckAccessSpinner.succeed(`You are in the staff of this enonce`); - } - - { - console.log(chalk.cyan(`Please wait while we ${ this.publish ? 'publish' : 'unpublish' } the enonce...`)); - - try { - await DojoBackendManager.changeEnoncePublishedStatus(enonce, this.publish); - } catch ( error ) { - return; - } - } - } -} - - -export default EnoncePublishUnpublishCommandBase; \ No newline at end of file diff --git a/NodeApp/src/commander/enonce/EnonceUnpublishCommand.ts b/NodeApp/src/commander/enonce/EnonceUnpublishCommand.ts deleted file mode 100644 index 2a3e3d3..0000000 --- a/NodeApp/src/commander/enonce/EnonceUnpublishCommand.ts +++ /dev/null @@ -1,10 +0,0 @@ -import EnoncePublishUnpublishCommandBase from './EnoncePublishUnpublishCommandBase'; - - -class EnonceUnpublishCommand extends EnoncePublishUnpublishCommandBase { - protected commandName: string = 'unpublish'; - protected publish: boolean = false; -} - - -export default new EnonceUnpublishCommand(); \ No newline at end of file diff --git a/NodeApp/src/commander/exercice/ExerciceCommand.ts b/NodeApp/src/commander/exercice/ExerciceCommand.ts deleted file mode 100644 index 27a7345..0000000 --- a/NodeApp/src/commander/exercice/ExerciceCommand.ts +++ /dev/null @@ -1,23 +0,0 @@ -import CommanderCommand from '../CommanderCommand'; -import ExerciceCreateCommand from './ExerciceCreateCommand'; -import ExerciceRunCommand from './ExerciceRunCommand'; - - -class ExerciceCommand extends CommanderCommand { - protected commandName: string = 'exercice'; - - protected defineCommand() { - this.command - .description('manage an exercice'); - } - - protected defineSubCommands() { - ExerciceCreateCommand.registerOnCommand(this.command); - ExerciceRunCommand.registerOnCommand(this.command); - } - - protected async commandAction(options: any): Promise<void> { } -} - - -export default new ExerciceCommand(); \ No newline at end of file diff --git a/NodeApp/src/commander/exercice/ExerciceCreateCommand.ts b/NodeApp/src/commander/exercice/ExerciceCreateCommand.ts deleted file mode 100644 index ccd761f..0000000 --- a/NodeApp/src/commander/exercice/ExerciceCreateCommand.ts +++ /dev/null @@ -1,91 +0,0 @@ -import CommanderCommand from '../CommanderCommand'; -import chalk from 'chalk'; -import GitlabManager from '../../managers/GitlabManager'; -import GitlabUser from '../../shared/types/Gitlab/GitlabUser'; -import Enonce from '../../sharedByClients/models/Enonce'; -import ora from 'ora'; -import DojoBackendManager from '../../managers/DojoBackendManager'; -import Exercice from '../../sharedByClients/models/Exercice'; -import AccessesHelper from '../../helpers/AccessesHelper'; - - -class ExerciceCreateCommand extends CommanderCommand { - protected commandName: string = 'create'; - - protected defineCommand() { - this.command - .description('create a new exercice from an enonce') - .requiredOption('-e, --enonce <value>', 'enonce source (Dojo enonce ID, Dojo enonce name or Gitlab enonce URL)') - .option('-i, --members_id <ids...>', 'list of gitlab members ids (group\'s student) to add to the repository') - .option('-u, --members_username <usernames...>', 'list of gitlab members username (group\'s student) to add to the repository') - .action(this.commandAction.bind(this)); - } - - protected async commandAction(options: any): Promise<void> { - let members!: Array<GitlabUser> | false; - let enonce!: Enonce | undefined; - - // Check access and retrieve data - { - console.log(chalk.cyan('Please wait while we verify and retrieve data...')); - - if ( !await AccessesHelper.checkStudent() ) { - return; - } - - members = await GitlabManager.fetchMembers(options); - if ( !members ) { - return; - } - - ora('Checking enonce:').start().info(); - const enonceGetSpinner: ora.Ora = ora({ - text : 'Checking if enonce exists', - indent: 4 - }).start(); - enonce = await DojoBackendManager.getEnonce(options.enonce); - if ( !enonce ) { - enonceGetSpinner.fail(`Enonce "${ options.enonce }" doesn't exists`); - return; - } - enonceGetSpinner.succeed(`Enonce "${ options.enonce }" exists`); - - const enoncePublishedSpinner: ora.Ora = ora({ - text : 'Checking if enonce is published', - indent: 4 - }).start(); - if ( !enonce.published ) { - enoncePublishedSpinner.fail(`Enonce "${ enonce.name }" isn't published`); - return; - } - enoncePublishedSpinner.succeed(`Enonce "${ enonce.name }" is published`); - } - - //Create the exercice - { - console.log(chalk.cyan('Please wait while we are creating the exercice...')); - - try { - const exercice: Exercice = await DojoBackendManager.createExercice((enonce as Enonce).name, members); - - const oraInfo = (message: string) => { - ora({ - text : message, - indent: 4 - }).start().info(); - }; - - oraInfo(`${ chalk.magenta('Id:') } ${ exercice.id }`); - oraInfo(`${ chalk.magenta('Name:') } ${ exercice.name }`); - oraInfo(`${ chalk.magenta('Web URL:') } ${ exercice.gitlabCreationInfo.web_url }`); - oraInfo(`${ chalk.magenta('HTTP Repo:') } ${ exercice.gitlabCreationInfo.http_url_to_repo }`); - oraInfo(`${ chalk.magenta('SSH Repo:') } ${ exercice.gitlabCreationInfo.ssh_url_to_repo }`); - } catch ( error ) { - return; - } - } - } -} - - -export default new ExerciceCreateCommand(); \ No newline at end of file diff --git a/NodeApp/src/commander/exercise/ExerciseCommand.ts b/NodeApp/src/commander/exercise/ExerciseCommand.ts new file mode 100644 index 0000000..ef2c3f2 --- /dev/null +++ b/NodeApp/src/commander/exercise/ExerciseCommand.ts @@ -0,0 +1,23 @@ +import CommanderCommand from '../CommanderCommand'; +import ExerciseCreateCommand from './ExerciseCreateCommand'; +import ExerciseRunCommand from './ExerciseRunCommand'; + + +class ExerciseCommand extends CommanderCommand { + protected commandName: string = 'exercise'; + + protected defineCommand() { + this.command + .description('manage an exercise'); + } + + protected defineSubCommands() { + ExerciseCreateCommand.registerOnCommand(this.command); + ExerciseRunCommand.registerOnCommand(this.command); + } + + protected async commandAction(options: any): Promise<void> { } +} + + +export default new ExerciseCommand(); \ No newline at end of file diff --git a/NodeApp/src/commander/exercise/ExerciseCreateCommand.ts b/NodeApp/src/commander/exercise/ExerciseCreateCommand.ts new file mode 100644 index 0000000..9116ff3 --- /dev/null +++ b/NodeApp/src/commander/exercise/ExerciseCreateCommand.ts @@ -0,0 +1,91 @@ +import CommanderCommand from '../CommanderCommand'; +import chalk from 'chalk'; +import GitlabManager from '../../managers/GitlabManager'; +import GitlabUser from '../../shared/types/Gitlab/GitlabUser'; +import ora from 'ora'; +import DojoBackendManager from '../../managers/DojoBackendManager'; +import AccessesHelper from '../../helpers/AccessesHelper'; +import Assignment from '../../sharedByClients/models/Assignment'; +import Exercise from '../../sharedByClients/models/Exercise'; + + +class ExerciseCreateCommand extends CommanderCommand { + protected commandName: string = 'create'; + + protected defineCommand() { + this.command + .description('create a new exercise from an assignment') + .requiredOption('-a, --assignment <value>', 'assignment source (Dojo assignment ID, Dojo assignment name or Gitlab assignment URL)') + .option('-i, --members_id <ids...>', 'list of gitlab members ids (group\'s student) to add to the repository') + .option('-u, --members_username <usernames...>', 'list of gitlab members username (group\'s student) to add to the repository') + .action(this.commandAction.bind(this)); + } + + protected async commandAction(options: any): Promise<void> { + let members!: Array<GitlabUser> | false; + let assignment!: Assignment | undefined; + + // Check access and retrieve data + { + console.log(chalk.cyan('Please wait while we verify and retrieve data...')); + + if ( !await AccessesHelper.checkStudent() ) { + return; + } + + members = await GitlabManager.fetchMembers(options); + if ( !members ) { + return; + } + + ora('Checking assignment:').start().info(); + const assignmentGetSpinner: ora.Ora = ora({ + text : 'Checking if assignment exists', + indent: 4 + }).start(); + assignment = await DojoBackendManager.getAssignment(options.assignment); + if ( !assignment ) { + assignmentGetSpinner.fail(`Assignment "${ options.assignment }" doesn't exists`); + return; + } + assignmentGetSpinner.succeed(`Assignment "${ options.assignment }" exists`); + + const assignmentPublishedSpinner: ora.Ora = ora({ + text : 'Checking if assignment is published', + indent: 4 + }).start(); + if ( !assignment.published ) { + assignmentPublishedSpinner.fail(`Assignment "${ assignment.name }" isn't published`); + return; + } + assignmentPublishedSpinner.succeed(`Assignment "${ assignment.name }" is published`); + } + + //Create the exercise + { + console.log(chalk.cyan('Please wait while we are creating the exercise...')); + + try { + const exercise: Exercise = await DojoBackendManager.createExercise((assignment as Assignment).name, members); + + const oraInfo = (message: string) => { + ora({ + text : message, + indent: 4 + }).start().info(); + }; + + oraInfo(`${ chalk.magenta('Id:') } ${ exercise.id }`); + oraInfo(`${ chalk.magenta('Name:') } ${ exercise.name }`); + oraInfo(`${ chalk.magenta('Web URL:') } ${ exercise.gitlabCreationInfo.web_url }`); + oraInfo(`${ chalk.magenta('HTTP Repo:') } ${ exercise.gitlabCreationInfo.http_url_to_repo }`); + oraInfo(`${ chalk.magenta('SSH Repo:') } ${ exercise.gitlabCreationInfo.ssh_url_to_repo }`); + } catch ( error ) { + return; + } + } + } +} + + +export default new ExerciseCreateCommand(); \ No newline at end of file diff --git a/NodeApp/src/commander/exercice/ExerciceRunCommand.ts b/NodeApp/src/commander/exercise/ExerciseRunCommand.ts similarity index 66% rename from NodeApp/src/commander/exercice/ExerciceRunCommand.ts rename to NodeApp/src/commander/exercise/ExerciseRunCommand.ts index 4130206..7fdd21b 100644 --- a/NodeApp/src/commander/exercice/ExerciceRunCommand.ts +++ b/NodeApp/src/commander/exercise/ExerciseRunCommand.ts @@ -4,29 +4,29 @@ import fs from 'node:fs'; import ora from 'ora'; import util from 'util'; import { exec } from 'child_process'; -import SharedEnonceHelper from '../../shared/helpers/Dojo/SharedEnonceHelper'; -import EnonceFile from '../../shared/types/Dojo/EnonceFile'; import chalk from 'chalk'; -import ExerciceDockerCompose from '../../sharedByClients/helpers/Dojo/ExerciceDockerCompose'; import * as os from 'os'; import path from 'path'; -import ExerciceResultsValidation from '../../sharedByClients/helpers/Dojo/ExerciceResultsValidation'; -import ExerciceCheckerError from '../../shared/types/Dojo/ExerciceCheckerError'; -import ClientsSharedExerciceHelper from '../../sharedByClients/helpers/Dojo/ClientsSharedExerciceHelper'; import ClientsSharedConfig from '../../sharedByClients/config/ClientsSharedConfig'; +import AssignmentFile from '../../shared/types/Dojo/AssignmentFile'; +import ExerciseDockerCompose from '../../sharedByClients/helpers/Dojo/ExerciseDockerCompose'; +import ExerciseResultsValidation from '../../sharedByClients/helpers/Dojo/ExerciseResultsValidation'; +import SharedAssignmentHelper from '../../shared/helpers/Dojo/SharedAssignmentHelper'; +import ExerciseCheckerError from '../../shared/types/Dojo/ExerciseCheckerError'; +import ClientsSharedExerciseHelper from '../../sharedByClients/helpers/Dojo/ClientsSharedExerciseHelper'; const execAsync = util.promisify(exec); -class ExerciceRunCommand extends CommanderCommand { +class ExerciseRunCommand extends CommanderCommand { protected commandName: string = 'run'; private readonly dateISOString: string = (new Date()).toISOString().replace(/:/g, '_').replace(/\./g, '_'); private readonly folderResultsVolume: string = path.join(os.homedir(), 'DojoExecutions', `dojo_execLogs_${ this.dateISOString }`); private readonly folderResultsDojo: string = path.join(this.folderResultsVolume, `Dojo/`); - private readonly folderResultsExercice: string = path.join(this.folderResultsVolume, `Exercice/`); + private readonly folderResultsExercise: string = path.join(this.folderResultsVolume, `Exercise/`); private readonly projectName: string = `${ ClientsSharedConfig.dockerCompose.projectName }_${ this.dateISOString.toLowerCase() }`; @@ -34,8 +34,8 @@ class ExerciceRunCommand extends CommanderCommand { protected defineCommand() { this.command - .description('locally run an exercice') - .option('-p, --path <value>', 'exercice path', Config.folders.defaultLocalExercice) + .description('locally run an exercise') + .option('-p, --path <value>', 'exercise path', Config.folders.defaultLocalExercise) .action(this.commandAction.bind(this)); } @@ -47,61 +47,61 @@ class ExerciceRunCommand extends CommanderCommand { } protected async commandAction(options: any): Promise<void> { - const localExercicePath = options.path ?? Config.folders.defaultLocalExercice; + const localExercisePath = options.path ?? Config.folders.defaultLocalExercise; - let enonceFile: EnonceFile; - let exerciceDockerCompose: ExerciceDockerCompose; - let exerciceResultsValidation: ExerciceResultsValidation; + let assignmentFile: AssignmentFile; + let exerciseDockerCompose: ExerciseDockerCompose; + let exerciseResultsValidation: ExerciseResultsValidation; - // Step 1: Check requirements (if it's an exercice folder and if Docker deamon is running) + // Step 1: Check requirements (if it's an exercise folder and if Docker deamon is running) { console.log(chalk.cyan('Please wait while we are checking and creating dependencies...')); // Create result temp folder fs.mkdirSync(this.folderResultsVolume, { recursive: true }); fs.mkdirSync(this.folderResultsDojo, { recursive: true }); - fs.mkdirSync(this.folderResultsExercice, { recursive: true }); + fs.mkdirSync(this.folderResultsExercise, { recursive: true }); ora({ - text : `Checking exercice content:`, + text : `Checking exercise content:`, indent: 4 }).start().info(); - // Exercice folder + // Exercise folder { const spinner: ora.Ora = ora({ - text : `Checking exercice folder`, + text : `Checking exercise folder`, indent: 8 }).start(); const files = fs.readdirSync(options.path); - const missingFiles = Config.exercice.neededFiles.map((file: string): [ string, boolean ] => [ file, files.includes(file) ]).filter((file: [ string, boolean ]) => !file[1]); + const missingFiles = Config.exercise.neededFiles.map((file: string): [ string, boolean ] => [ file, files.includes(file) ]).filter((file: [ string, boolean ]) => !file[1]); if ( missingFiles.length > 0 ) { - spinner.fail(`The exercice folder is missing the following files: ${ missingFiles.map((file: [ string, boolean ]) => file[0]).join(', ') }`); + spinner.fail(`The exercise folder is missing the following files: ${ missingFiles.map((file: [ string, boolean ]) => file[0]).join(', ') }`); return; } - spinner.succeed(`The exercice folder contains all the needed files`); + spinner.succeed(`The exercise folder contains all the needed files`); } - // dojo.enonce validity + // dojo.assignment validity { const spinner: ora.Ora = ora({ - text : `Checking ${ Config.enonce.filename } file`, + text : `Checking ${ Config.assignment.filename } file`, indent: 8 }).start(); - const validationResults = SharedEnonceHelper.validateDescriptionFile(`${ options.path }/${ Config.enonce.filename }`); + const validationResults = SharedAssignmentHelper.validateDescriptionFile(`${ options.path }/${ Config.assignment.filename }`); if ( !validationResults.isValid ) { - spinner.fail(`The ${ Config.enonce.filename } file is invalid: ${ JSON.stringify(validationResults.errors) }`); + spinner.fail(`The ${ Config.assignment.filename } file is invalid: ${ JSON.stringify(validationResults.errors) }`); return; } else { - enonceFile = validationResults.results!; + assignmentFile = validationResults.results!; } - spinner.succeed(`The ${ Config.enonce.filename } file is valid`); + spinner.succeed(`The ${ Config.assignment.filename } file is valid`); } // Docker deamon @@ -112,7 +112,7 @@ class ExerciceRunCommand extends CommanderCommand { }).start(); try { - await execAsync(`cd "${ Config.folders.defaultLocalExercice }";docker ps`); + await execAsync(`cd "${ Config.folders.defaultLocalExercise }";docker ps`); } catch ( error ) { spinner.fail(`The Docker deamon is not running`); return; @@ -125,27 +125,27 @@ class ExerciceRunCommand extends CommanderCommand { // Step 2: Run docker-compose file { - console.log(chalk.cyan('Please wait while we are running the exercice...')); + console.log(chalk.cyan('Please wait while we are running the exercise...')); - const composeOverridePath: string = path.join(localExercicePath, 'docker-compose-override.yml'); + const composeOverridePath: string = path.join(localExercisePath, 'docker-compose-override.yml'); - const composeOverride = fs.readFileSync(path.join(__dirname, '../../../assets/docker-compose-override.yml'), 'utf8').replace('{{VOLUME_NAME}}', enonceFile.result.volume).replace('{{MOUNT_PATH}}', this.folderResultsExercice); + const composeOverride = fs.readFileSync(path.join(__dirname, '../../../assets/docker-compose-override.yml'), 'utf8').replace('{{VOLUME_NAME}}', assignmentFile.result.volume).replace('{{MOUNT_PATH}}', this.folderResultsExercise); fs.writeFileSync(composeOverridePath, composeOverride); - exerciceDockerCompose = new ExerciceDockerCompose(this.projectName, enonceFile, localExercicePath, [ composeOverridePath ]); + exerciseDockerCompose = new ExerciseDockerCompose(this.projectName, assignmentFile, localExercisePath, [ composeOverridePath ]); try { await new Promise<void>((resolve, reject) => { let spinner: ora.Ora; - exerciceDockerCompose.events.on('step', (name: string, message: string) => { + exerciseDockerCompose.events.on('step', (name: string, message: string) => { spinner = ora({ text : message, indent: 4 }).start(); }); - exerciceDockerCompose.events.on('endStep', (stepName: string, message: string, error: boolean) => { + exerciseDockerCompose.events.on('endStep', (stepName: string, message: string, error: boolean) => { if ( error ) { spinner.fail(message); } else { @@ -153,18 +153,18 @@ class ExerciceRunCommand extends CommanderCommand { } }); - exerciceDockerCompose.events.on('finished', (success: boolean, exitCode: number) => { + exerciseDockerCompose.events.on('finished', (success: boolean, exitCode: number) => { success ? resolve() : reject(); }); - exerciceDockerCompose.run(true); + exerciseDockerCompose.run(true); }); } catch ( error ) { } fs.rmSync(composeOverridePath); - fs.writeFileSync(this.fileComposeLogs, exerciceDockerCompose.allLogs); + fs.writeFileSync(this.fileComposeLogs, exerciseDockerCompose.allLogs); - if ( !exerciceDockerCompose.success ) { + if ( !exerciseDockerCompose.success ) { this.displayExecutionLogs(); return; } @@ -175,20 +175,20 @@ class ExerciceRunCommand extends CommanderCommand { { console.log(chalk.cyan('Please wait while we are checking the results...')); - exerciceResultsValidation = new ExerciceResultsValidation(this.folderResultsDojo, this.folderResultsExercice); + exerciseResultsValidation = new ExerciseResultsValidation(this.folderResultsDojo, this.folderResultsExercise); try { await new Promise<void>((resolve, reject) => { let spinner: ora.Ora; - exerciceResultsValidation.events.on('step', (name: string, message: string) => { + exerciseResultsValidation.events.on('step', (name: string, message: string) => { spinner = ora({ text : message, indent: 4 }).start(); }); - exerciceResultsValidation.events.on('endStep', (stepName: string, message: string, error: boolean) => { + exerciseResultsValidation.events.on('endStep', (stepName: string, message: string, error: boolean) => { if ( error ) { if ( stepName == 'CHECK_SIZE' ) { spinner.warn(message); @@ -200,11 +200,11 @@ class ExerciceRunCommand extends CommanderCommand { } }); - exerciceResultsValidation.events.on('finished', (success: boolean, exitCode: number) => { - success || exitCode == ExerciceCheckerError.EXERCICE_RESULTS_FOLDER_TOO_BIG ? resolve() : reject(); + exerciseResultsValidation.events.on('finished', (success: boolean, exitCode: number) => { + success || exitCode == ExerciseCheckerError.EXERCISE_RESULTS_FOLDER_TOO_BIG ? resolve() : reject(); }); - exerciceResultsValidation.run(); + exerciseResultsValidation.run(); }); } catch ( error ) { this.displayExecutionLogs(); @@ -215,7 +215,7 @@ class ExerciceRunCommand extends CommanderCommand { // Step 4: Display results + Volume location { - ClientsSharedExerciceHelper.displayExecutionResults(exerciceResultsValidation.exerciceResults!, exerciceDockerCompose.exitCode, { + ClientsSharedExerciseHelper.displayExecutionResults(exerciseResultsValidation.exerciseResults!, exerciseDockerCompose.exitCode, { INFO : chalk.bold, SUCCESS: chalk.green, FAILURE: chalk.red @@ -225,4 +225,4 @@ class ExerciceRunCommand extends CommanderCommand { } -export default new ExerciceRunCommand(); \ No newline at end of file +export default new ExerciseRunCommand(); \ No newline at end of file diff --git a/NodeApp/src/config/Config.ts b/NodeApp/src/config/Config.ts index c384a41..dca31f4 100644 --- a/NodeApp/src/config/Config.ts +++ b/NodeApp/src/config/Config.ts @@ -7,14 +7,14 @@ class Config { }; public readonly folders: { - defaultLocalExercice: string + defaultLocalExercise: string }; - public enonce: { + public assignment: { filename: string }; - public readonly exercice: { + public readonly exercise: { neededFiles: Array<string> }; @@ -25,15 +25,15 @@ class Config { }; this.folders = { - defaultLocalExercice: process.env.LOCAL_EXERCICE_DEFAULT_FOLDER || './' + defaultLocalExercise: process.env.LOCAL_EXERCISE_DEFAULT_FOLDER || './' }; - this.enonce = { - filename: process.env.ENONCE_FILENAME || '' + this.assignment = { + filename: process.env.ASSIGNMENT_FILENAME || '' }; - this.exercice = { - neededFiles: JSON.parse(process.env.EXERCICE_NEEDED_FILES || '[]') + this.exercise = { + neededFiles: JSON.parse(process.env.EXERCISE_NEEDED_FILES || '[]') }; } } diff --git a/NodeApp/src/managers/DojoBackendManager.ts b/NodeApp/src/managers/DojoBackendManager.ts index d9283bb..64c56cb 100644 --- a/NodeApp/src/managers/DojoBackendManager.ts +++ b/NodeApp/src/managers/DojoBackendManager.ts @@ -2,11 +2,11 @@ import axios, { AxiosError } from 'axios'; import ora from 'ora'; import ApiRoute from '../sharedByClients/types/Dojo/ApiRoute'; import { StatusCodes } from 'http-status-codes'; -import Enonce from '../sharedByClients/models/Enonce'; import GitlabUser from '../shared/types/Gitlab/GitlabUser'; -import Exercice from '../sharedByClients/models/Exercice'; -import DojoResponse from '../shared/types/Dojo/DojoResponse'; import ClientsSharedConfig from '../sharedByClients/config/ClientsSharedConfig'; +import Assignment from '../sharedByClients/models/Assignment'; +import DojoBackendResponse from '../shared/types/Dojo/DojoBackendResponse'; +import Exercise from '../sharedByClients/models/Exercise'; class DojoBackendManager { @@ -14,9 +14,9 @@ class DojoBackendManager { return `${ ClientsSharedConfig.apiURL }${ route }`; } - public async getEnonce(nameOrUrl: string): Promise<Enonce | undefined> { + public async getAssignment(nameOrUrl: string): Promise<Assignment | undefined> { try { - return (await axios.get<DojoResponse<Enonce>>(this.getApiUrl(ApiRoute.ENONCE_GET).replace('{{nameOrUrl}}', encodeURIComponent(nameOrUrl)))).data.data; + return (await axios.get<DojoBackendResponse<Assignment>>(this.getApiUrl(ApiRoute.ASSIGNMENT_GET).replace('{{nameOrUrl}}', encodeURIComponent(nameOrUrl)))).data.data; } catch ( error ) { return undefined; } @@ -59,21 +59,21 @@ class DojoBackendManager { } } - public async createEnonce(name: string, members: Array<GitlabUser>, templateIdOrNamespace: string | null, verbose: boolean = true): Promise<Enonce> { - const spinner: ora.Ora = ora('Creating enonce...'); + public async createAssignment(name: string, members: Array<GitlabUser>, templateIdOrNamespace: string | null, verbose: boolean = true): Promise<Assignment> { + const spinner: ora.Ora = ora('Creating assignment...'); if ( verbose ) { spinner.start(); } try { - const response = await axios.post<DojoResponse<Enonce>>(this.getApiUrl(ApiRoute.ENONCE_CREATE), Object.assign({ - name : name, - members: JSON.stringify(members) - }, templateIdOrNamespace ? { template: templateIdOrNamespace } : {})); + const response = await axios.post<DojoBackendResponse<Assignment>>(this.getApiUrl(ApiRoute.ASSIGNMENT_CREATE), Object.assign({ + name : name, + members: JSON.stringify(members) + }, templateIdOrNamespace ? { template: templateIdOrNamespace } : {})); if ( verbose ) { - spinner.succeed(`Enonce successfully created`); + spinner.succeed(`Assignment successfully created`); } return response.data.data; @@ -82,13 +82,13 @@ class DojoBackendManager { if ( error instanceof AxiosError ) { if ( error.response ) { if ( error.response.status === StatusCodes.CONFLICT ) { - spinner.fail(`The enonce name is already used. Please choose another one.`); + spinner.fail(`The assignment name is already used. Please choose another one.`); } else { - spinner.fail(`Enonce creation error: ${ error.response.statusText }`); + spinner.fail(`Assignment creation error: ${ error.response.statusText }`); } } } else { - spinner.fail(`Enonce creation error: unknown error`); + spinner.fail(`Assignment creation error: unknown error`); } } @@ -96,18 +96,18 @@ class DojoBackendManager { } } - public async createExercice(enonceName: string, members: Array<GitlabUser>, verbose: boolean = true): Promise<Exercice> { - const spinner: ora.Ora = ora('Creating exercice...'); + public async createExercise(assignmentName: string, members: Array<GitlabUser>, verbose: boolean = true): Promise<Exercise> { + const spinner: ora.Ora = ora('Creating exercise...'); if ( verbose ) { spinner.start(); } try { - const response = await axios.post<DojoResponse<Exercice>>(this.getApiUrl(ApiRoute.EXERCICE_CREATE).replace('{{nameOrUrl}}', encodeURIComponent(enonceName)), { members: JSON.stringify(members) }); + const response = await axios.post<DojoBackendResponse<Exercise>>(this.getApiUrl(ApiRoute.EXERCISE_CREATE).replace('{{nameOrUrl}}', encodeURIComponent(assignmentName)), { members: JSON.stringify(members) }); if ( verbose ) { - spinner.succeed(`Exercice successfully created`); + spinner.succeed(`Exercise successfully created`); } return response.data.data; @@ -116,13 +116,13 @@ class DojoBackendManager { if ( error instanceof AxiosError ) { if ( error.response ) { if ( error.response.status === StatusCodes.CONFLICT ) { - spinner.fail(`You've reached the max number of exercice of this enonce.`); + spinner.fail(`You've already reached the max number of exercise of this assignment.`); } else { - spinner.fail(`Exercice creation error: ${ error.response.statusText }`); + spinner.fail(`Exercise creation error: ${ error.response.statusText }`); } } } else { - spinner.fail(`Exercice creation error: unknown error`); + spinner.fail(`Exercise creation error: unknown error`); } } @@ -130,7 +130,7 @@ class DojoBackendManager { } } - public async changeEnoncePublishedStatus(enonce: Enonce, publish: boolean, verbose: boolean = true) { + public async changeAssignmentPublishedStatus(assignment: Assignment, publish: boolean, verbose: boolean = true) { const spinner: ora.Ora = ora('Changing published status...'); if ( verbose ) { @@ -138,19 +138,19 @@ class DojoBackendManager { } try { - await axios.patch<DojoResponse<null>>(this.getApiUrl(publish ? ApiRoute.ENONCE_PUBLISH : ApiRoute.ENONCE_UNPUBLISH).replace('{{nameOrUrl}}', encodeURIComponent(enonce.name)), {}); + await axios.patch<DojoBackendResponse<null>>(this.getApiUrl(publish ? ApiRoute.ASSIGNMENT_PUBLISH : ApiRoute.ASSIGNMENT_UNPUBLISH).replace('{{nameOrUrl}}', encodeURIComponent(assignment.name)), {}); if ( verbose ) { - spinner.succeed(`Enonce ${ enonce.name } successfully ${ publish ? 'published' : 'unpublished' }`); + spinner.succeed(`Assignment ${ assignment.name } successfully ${ publish ? 'published' : 'unpublished' }`); } return; } catch ( error ) { if ( verbose ) { if ( error instanceof AxiosError && error.response ) { - spinner.fail(`Enonce visibility change error: ${ error.response.statusText }`); + spinner.fail(`Assignment visibility change error: ${ error.response.statusText }`); } else { - spinner.fail(`Enonce visibility change error: unknown error`); + spinner.fail(`Assignment visibility change error: unknown error`); } } -- GitLab