Skip to content
Snippets Groups Projects
Commit a5e72b83 authored by michael.minelli's avatar michael.minelli
Browse files

Add exercice creation

parent 50adb0e1
No related branches found
No related tags found
No related merge requests found
......@@ -2,6 +2,7 @@ import { Command } from 'commander';
import Config from '../config/Config';
import EnonceCommand from './enonce/EnonceCommand';
import SessionCommand from './session/SessionCommand';
import ExerciceCommand from './exercice/ExerciceCommand';
class CommanderApp {
......@@ -32,6 +33,7 @@ class CommanderApp {
private registerCommands() {
SessionCommand.registerOnCommand(this.program);
EnonceCommand.registerOnCommand(this.program);
ExerciceCommand.registerOnCommand(this.program);
}
}
......
import CommanderCommand from '../CommanderCommand';
import ExerciceCreateCommand from './ExerciceCreateCommand';
class ExerciceCommand extends CommanderCommand {
protected commandName: string = 'exercice';
private static _instance: ExerciceCommand;
private constructor() { super(); }
public static get instance(): ExerciceCommand {
if ( !ExerciceCommand._instance ) {
ExerciceCommand._instance = new ExerciceCommand();
}
return ExerciceCommand._instance;
}
protected defineCommand() {
this.command
.description('manage an exercice');
}
protected defineSubCommands() {
ExerciceCreateCommand.registerOnCommand(this.command);
}
protected async commandAction(options: any): Promise<void> { }
}
export default ExerciceCommand.instance;
\ No newline at end of file
import CommanderCommand from '../CommanderCommand';
import chalk from 'chalk';
import GitlabManager from '../../managers/GitlabManager';
import SessionManager from '../../managers/SessionManager';
import GitlabUser from '../../shared/types/Gitlab/GitlabUser';
import Enonce from '../../types/Enonce';
import ora from 'ora';
import DojoBackendManager from '../../managers/DojoBackendManager';
import Exercice from '../../types/Exercice';
class ExerciceCreateCommand extends CommanderCommand {
protected commandName: string = 'create';
private static _instance: ExerciceCreateCommand;
private constructor() { super(); }
public static get instance(): ExerciceCreateCommand {
if ( !ExerciceCreateCommand._instance ) {
ExerciceCreateCommand._instance = new ExerciceCreateCommand();
}
return ExerciceCreateCommand._instance;
}
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));
}
private async checkAccesses(): Promise<boolean> {
let sessionResult = await SessionManager.testSession(true, [ 'student' ]);
if ( !sessionResult ) {
return false;
}
return (await GitlabManager.testToken(true)).every(result => result);
}
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 this.checkAccesses() ) {
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();
//TODO : Check if the enonce is published
//if ( false ) {
//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 ExerciceCreateCommand.instance;
\ No newline at end of file
......@@ -6,6 +6,7 @@ import { StatusCodes } from 'http-status-codes';
import Enonce from '../types/Enonce';
import GitlabUser from '../shared/types/Gitlab/GitlabUser';
import DojoResponse from '../types/DojoResponse';
import Exercice from '../types/Exercice';
class DojoBackendManager {
......@@ -106,6 +107,40 @@ class DojoBackendManager {
throw error;
}
}
public async createExercice(enonceName: string, members: Array<GitlabUser>, verbose: boolean = true): Promise<Exercice> {
const spinner: ora.Ora = ora('Creating exercice...');
if ( verbose ) {
spinner.start();
}
try {
const response = await axios.post<DojoResponse<Exercice>>(this.getApiUrl(ApiRoutes.EXERCICE_CREATE).replace('{{nameOrUrl}}', String(enonceName)), { members: JSON.stringify(members) });
if ( verbose ) {
spinner.succeed(`Exercice successfully created`);
}
return response.data.data;
} catch ( error ) {
if ( verbose ) {
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.`);
} else {
spinner.fail(`Exercice creation error: ${ error.response.statusText }`);
}
}
} else {
spinner.fail(`Exercice creation error: unknown error`);
}
}
throw error;
}
}
}
......
......@@ -4,6 +4,7 @@ enum ApiRoutes {
GITLAB_CHECK_TEMPLATE_ACCESS = '/gitlab/project/{{id}}/checkTemplateAccess',
ENONCE_GET = '/enonces/{{nameOrUrl}}',
ENONCE_CREATE = '/enonces',
EXERCICE_CREATE = '/enonces/{{nameOrUrl}}/exercices',
}
......
import GitlabRepository from '../shared/types/Gitlab/GitlabRepository';
interface Exercice {
id: string;
enonceName: string;
name: string;
gitlabId: number;
gitlabLink: string;
gitlabCreationInfo: GitlabRepository;
gitlabLastInfo: GitlabRepository;
gitlabLastInfoTs: number;
}
export default Exercice;
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment