├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── PULL_REQUEST_TEMPLATE.md └── workflows │ └── Flutter-CI.yml ├── .gitignore ├── .travis.yml ├── .vscode └── settings.json ├── CODE_OF_CONDUCT.md ├── LICENSE ├── README.md ├── app.json ├── docker-compose.yml ├── labellab-client ├── .dockerignore ├── .env.example ├── .eslintrc.js ├── .gitignore ├── Dockerfile ├── README.md ├── config │ ├── env.js │ ├── jest │ │ ├── cssTransform.js │ │ └── fileTransform.js │ ├── modules.js │ ├── paths.js │ ├── pnpTs.js │ ├── webpack.config.js │ └── webpackDevServer.config.js ├── package-lock.json ├── package.json ├── prettier.config.js ├── public │ ├── favicon.ico │ ├── index.html │ └── manifest.json ├── scripts │ ├── build.js │ ├── start.js │ └── test.js └── src │ ├── App.css │ ├── App.js │ ├── App.test.js │ ├── __tests__ │ ├── components │ │ ├── dashboard.test.js │ │ ├── issueDetails.test.js │ │ ├── issues.test.js │ │ └── login.test.js │ └── reducers │ │ ├── authReducer.test.js │ │ ├── projectReducers.test.js │ │ └── registerReducer.test.js │ ├── actions │ ├── analytics.js │ ├── auth.js │ ├── image.js │ ├── index.js │ ├── issue.js │ ├── label.js │ ├── model.js │ ├── notification.js │ ├── project │ │ ├── fetchDetails.js │ │ ├── index.js │ │ ├── logs.js │ │ ├── member.js │ │ ├── pathTracking.js │ │ ├── projectDetails.js │ │ ├── search.js │ │ └── teams.js │ ├── register.js │ └── user.js │ ├── components │ ├── dashboard │ │ ├── css │ │ │ ├── dashboard.css │ │ │ └── previous.css │ │ ├── index.js │ │ └── previous.js │ ├── error │ │ ├── css │ │ │ └── notfound.css │ │ ├── notFound.js │ │ └── unauthorized.js │ ├── index.js │ ├── labeller │ │ ├── CalcBoundsHOC.js │ │ ├── Canvas.js │ │ ├── Figure.js │ │ ├── LabelingApp.js │ │ ├── LabelingAppHistoryHOC.js │ │ ├── LoadImageDataHOC.js │ │ ├── Sidebar.js │ │ ├── css │ │ │ └── LabelingApp.css │ │ ├── index.js │ │ └── utils.js │ ├── loading │ │ └── index.js │ ├── login │ │ ├── ForgotPassword.js │ │ ├── GithubOAuth.js │ │ ├── GoogleOAuth.js │ │ ├── ResetPassword.js │ │ ├── css │ │ │ ├── ForgotPassword.css │ │ │ ├── ResetPassword.css │ │ │ └── login.css │ │ └── index.js │ ├── logout │ │ └── index.js │ ├── model-editor │ │ ├── classifierEditor.js │ │ ├── css │ │ │ ├── classifierEditor.css │ │ │ └── modelEditor.css │ │ ├── index.js │ │ └── sub-modules │ │ │ ├── addModelEntityModal.js │ │ │ ├── css │ │ │ ├── addModelEntityModal.css │ │ │ ├── customBuilder.css │ │ │ ├── exporter.css │ │ │ ├── labelSelector.css │ │ │ ├── modelTester.css │ │ │ ├── preprocessingSelector.css │ │ │ ├── trainingGraphs.css │ │ │ ├── transferLearningBuilder.css │ │ │ └── uploadBuilder.css │ │ │ ├── customBuilder.js │ │ │ ├── exporter.js │ │ │ ├── labelSelector.js │ │ │ ├── modelParameterEditor.js │ │ │ ├── modelTester.js │ │ │ ├── options │ │ │ ├── layerOptions.js │ │ │ ├── lossOptions.js │ │ │ ├── metricOptions.js │ │ │ ├── optimizerOptions.js │ │ │ ├── preprocessingStepOptions.js │ │ │ └── transferLearningOptions.js │ │ │ ├── preprocessingSelector.js │ │ │ ├── trainingGraphs.js │ │ │ ├── transferLearningBuilder.js │ │ │ └── uploadBuilder.js │ ├── navbar │ │ ├── css │ │ │ ├── navbar.css │ │ │ └── searchbar.css │ │ ├── index.js │ │ ├── notification.js │ │ ├── project.js │ │ └── searchbar.js │ ├── profile │ │ ├── css │ │ │ ├── profile-card.css │ │ │ └── profile.css │ │ ├── index.js │ │ └── profile-card.js │ ├── project │ │ ├── analytics.js │ │ ├── chatroom.js │ │ ├── css │ │ │ ├── analytics.css │ │ │ ├── chatroom.css │ │ │ ├── images.css │ │ │ ├── index.css │ │ │ ├── issues.css │ │ │ ├── labelItem.css │ │ │ ├── models.css │ │ │ ├── projectDesc.css │ │ │ ├── searchUser.css │ │ │ ├── sidebar.css │ │ │ └── team.css │ │ ├── images.js │ │ ├── index.js │ │ ├── issue │ │ │ ├── issueActions.js │ │ │ ├── issueDetails.js │ │ │ └── issues.js │ │ ├── label │ │ │ ├── index.js │ │ │ └── labelItem.js │ │ ├── models.js │ │ ├── path-tracking.js │ │ ├── projectActivity.js │ │ ├── projectDesc.js │ │ ├── searchUser.js │ │ ├── sidebar.js │ │ ├── team.js │ │ └── teamDetails.js │ ├── redirect.js │ └── register │ │ ├── css │ │ └── register.css │ │ └── index.js │ ├── constants │ ├── analytics.js │ ├── auth.js │ ├── image.js │ ├── index.js │ ├── issue.js │ ├── label.js │ ├── model.js │ ├── notification.js │ ├── options.js │ ├── project │ │ ├── fetchDetails.js │ │ ├── index.js │ │ ├── logs.js │ │ ├── member.js │ │ ├── pathTracking.js │ │ ├── projectDetails.js │ │ ├── search.js │ │ └── teams.js │ ├── register.js │ ├── test.js │ └── user.js │ ├── index.css │ ├── index.js │ ├── logo.svg │ ├── reducers │ ├── analytics.js │ ├── auth.js │ ├── image.js │ ├── index.js │ ├── issue.js │ ├── label.js │ ├── logs.js │ ├── model.js │ ├── notification.js │ ├── project.js │ ├── register.js │ ├── search.js │ ├── searchUser.js │ ├── teams.js │ └── user.js │ ├── serviceWorker.js │ ├── static │ └── icons │ │ ├── github-logo.svg │ │ └── search.svg │ └── utils │ ├── FetchAPI.js │ ├── TestUtils.js │ ├── cardLoader │ ├── card-loader.css │ └── index.js │ ├── helpers.js │ ├── pR.js │ ├── store.js │ ├── token.js │ ├── validation.js │ └── webSocket.js ├── labellab-flask ├── .dockerignore ├── .envsample ├── .flake8 ├── .gcloudignore ├── Dockerfile ├── __init__.py ├── api │ ├── __init__.py │ ├── commands.py │ ├── config.py │ ├── controllers │ │ ├── __init__.py │ │ ├── analyticscontroller.py │ │ ├── chatroomcontroller.py │ │ ├── classificationscontroller.py │ │ ├── commentcontroller.py │ │ ├── imagescontroller.py │ │ ├── issuecontroller.py │ │ ├── labelscontroller.py │ │ ├── logscontroller.py │ │ ├── mlclassifierscontroller.py │ │ ├── notificationscontroller.py │ │ ├── projectscontroller.py │ │ ├── teamscontroller.py │ │ └── userscontroller.py │ ├── extensions.py │ ├── helpers │ │ ├── __init__.py │ │ ├── analytics.py │ │ ├── chatroom.py │ │ ├── classification.py │ │ ├── comment.py │ │ ├── email │ │ │ ├── email_template.py │ │ │ └── send_email.py │ │ ├── image.py │ │ ├── issue.py │ │ ├── label.py │ │ ├── labeldata.py │ │ ├── log.py │ │ ├── mlclassifier.py │ │ ├── notification.py │ │ ├── point.py │ │ ├── project.py │ │ ├── projectmember.py │ │ ├── team.py │ │ └── user.py │ ├── main.py │ ├── middleware │ │ ├── comment_decorator.py │ │ ├── image_access.py │ │ ├── image_labelling_access.py │ │ ├── issue_decorator.py │ │ ├── label_access.py │ │ ├── logs_decorator.py │ │ ├── model_access.py │ │ ├── project_admin_access.py │ │ ├── project_member_access.py │ │ └── project_owner_access.py │ ├── models │ │ ├── Classification.py │ │ ├── Comment.py │ │ ├── Image.py │ │ ├── Issue.py │ │ ├── Label.py │ │ ├── LabelData.py │ │ ├── Log.py │ │ ├── MLClassifier.py │ │ ├── Message.py │ │ ├── Notification.py │ │ ├── Point.py │ │ ├── ProjectMembers.py │ │ ├── Projects.py │ │ ├── RevokedToken.py │ │ ├── Team.py │ │ ├── User.py │ │ └── __init__.py │ ├── routes │ │ ├── __init__.py │ │ ├── analytics.py │ │ ├── chatroom.py │ │ ├── classifications.py │ │ ├── comments.py │ │ ├── images.py │ │ ├── issue.py │ │ ├── labels.py │ │ ├── logs.py │ │ ├── ml_files.py │ │ ├── mlclassifiers.py │ │ ├── notifications.py │ │ ├── projects.py │ │ ├── static.py │ │ ├── teams.py │ │ └── users.py │ └── serializers │ │ ├── __init__.py │ │ ├── classification.py │ │ ├── comment.py │ │ ├── image.py │ │ ├── issue.py │ │ ├── label.py │ │ ├── labeldata.py │ │ ├── mlclassifier.py │ │ ├── notification.py │ │ ├── point.py │ │ ├── project.py │ │ ├── projectmember.py │ │ ├── team.py │ │ └── user.py ├── app.py ├── app.yaml ├── boot.sh ├── docker.txt ├── docs │ ├── Makefile │ ├── labellab-flask.api.controllers.rst │ ├── labellab-flask.api.helpers.rst │ ├── labellab-flask.api.models.rst │ ├── labellab-flask.api.routes.rst │ ├── labellab-flask.api.rst │ ├── labellab-flask.api.serializers.rst │ ├── labellab-flask.rst │ ├── labellab-flask.tests.rst │ ├── make.bat │ ├── modules.rst │ └── source │ │ ├── conf.py │ │ └── index.rst ├── migrations │ ├── README │ ├── alembic.ini │ ├── env.py │ ├── script.py.mako │ └── versions │ │ └── f5462c8a9bc2_.py ├── ml │ ├── classifier.py │ ├── layer.py │ ├── preprocessing.py │ └── trainingplot.py ├── path_tracking │ ├── __init__.py │ ├── extract_exif.py │ └── sample6.png ├── pre-commit-config.yaml ├── prod.txt ├── requirements.txt ├── tests │ ├── __init__.py │ ├── test_comment.py │ ├── test_issue.py │ ├── test_label.py │ ├── test_login.py │ ├── test_project_and_team.py │ └── test_register.py ├── travis.txt └── uploads │ └── .gitignore ├── labellab-server ├── .dockerignore ├── .env.example ├── .eslintrc.json ├── .gitignore ├── Dockerfile ├── app.js ├── bin │ └── www ├── config │ ├── dbURI.js │ ├── githubPassport.js │ ├── googlePassport.js │ ├── jwtSecret.js │ ├── passport.js │ └── test.js ├── controller │ ├── analytics │ │ └── analyticsControls.js │ ├── auth │ │ ├── auth.js │ │ └── oauth.js │ ├── classification │ │ └── classificationControls.js │ ├── image │ │ └── imageControls.js │ ├── label │ │ └── labelControls.js │ ├── project │ │ └── projectControls.js │ └── user │ │ └── userControls.js ├── models │ ├── classification.js │ ├── image.js │ ├── label.js │ ├── project.js │ ├── projectMembers.js │ └── user.js ├── package-lock.json ├── package.json ├── public │ ├── classifications │ │ └── .gitignore │ ├── img │ │ └── .gitignore │ ├── project │ │ └── .gitignore │ ├── stylesheets │ │ └── style.css │ └── uploads │ │ └── .gitignore ├── routes │ ├── analytics │ │ └── routes.js │ ├── auth │ │ └── routes.js │ ├── classification │ │ └── routes.js │ ├── image │ │ └── routes.js │ ├── label │ │ └── routes.js │ ├── project │ │ └── routes.js │ ├── routes.js │ └── users │ │ └── routes.js ├── test │ ├── analytics.js │ ├── auth.js │ ├── classification.js │ ├── info.js │ ├── label.js │ ├── project.js │ └── user.js ├── utils │ ├── authValidations.js │ ├── color.js │ ├── error.js │ ├── labelData.js │ ├── months.js │ └── randomString.js └── views │ ├── authenticated.ejs │ └── error.ejs ├── labellab_mobile ├── .gitignore ├── .metadata ├── README.md ├── android │ ├── .project │ ├── .settings │ │ └── org.eclipse.buildship.core.prefs │ ├── app │ │ ├── .classpath │ │ ├── .project │ │ ├── .settings │ │ │ └── org.eclipse.buildship.core.prefs │ │ ├── build.gradle │ │ └── src │ │ │ ├── debug │ │ │ └── AndroidManifest.xml │ │ │ ├── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── kotlin │ │ │ │ └── org │ │ │ │ │ └── scorelab │ │ │ │ │ └── labellab_mobile │ │ │ │ │ └── MainActivity.kt │ │ │ └── res │ │ │ │ ├── drawable │ │ │ │ ├── launch_background.xml │ │ │ │ └── splash.png │ │ │ │ ├── mipmap-hdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ └── values │ │ │ │ └── styles.xml │ │ │ └── profile │ │ │ └── AndroidManifest.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ └── gradle-wrapper.properties │ └── settings.gradle ├── assets │ └── images │ │ └── splash.png ├── ios │ ├── Flutter │ │ ├── AppFrameworkInfo.plist │ │ ├── Debug.xcconfig │ │ └── Release.xcconfig │ ├── Podfile │ ├── Podfile.lock │ ├── Runner.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ └── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ ├── Runner.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── Runner │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── Icon-App-1024x1024@1x.png │ │ │ ├── Icon-App-20x20@1x.png │ │ │ ├── Icon-App-20x20@2x.png │ │ │ ├── Icon-App-20x20@3x.png │ │ │ ├── Icon-App-29x29@1x.png │ │ │ ├── Icon-App-29x29@2x.png │ │ │ ├── Icon-App-29x29@3x.png │ │ │ ├── Icon-App-40x40@1x.png │ │ │ ├── Icon-App-40x40@2x.png │ │ │ ├── Icon-App-40x40@3x.png │ │ │ ├── Icon-App-60x60@2x.png │ │ │ ├── Icon-App-60x60@3x.png │ │ │ ├── Icon-App-76x76@1x.png │ │ │ ├── Icon-App-76x76@2x.png │ │ │ └── Icon-App-83.5x83.5@2x.png │ │ └── LaunchImage.imageset │ │ │ ├── Contents.json │ │ │ ├── LaunchImage.png │ │ │ ├── LaunchImage@2x.png │ │ │ ├── LaunchImage@3x.png │ │ │ └── README.md │ │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ │ ├── Info.plist │ │ └── Runner-Bridging-Header.h ├── lib │ ├── data │ │ ├── interceptor │ │ │ ├── backend_url_interceptor.dart │ │ │ └── token_interceptor.dart │ │ ├── local │ │ │ ├── classifcation_provider.dart │ │ │ ├── entities │ │ │ │ ├── classification_entity.dart │ │ │ │ ├── issue_entity.dart │ │ │ │ └── project_entity.dart │ │ │ ├── issue_provider.dart │ │ │ ├── project_provider.dart │ │ │ └── user_provider.dart │ │ ├── remote │ │ │ ├── dto │ │ │ │ ├── api_response.dart │ │ │ │ ├── google_user_request.dart │ │ │ │ ├── login_response.dart │ │ │ │ ├── refresh_response.dart │ │ │ │ ├── register_response.dart │ │ │ │ └── time_value.dart │ │ │ ├── fake_server │ │ │ │ └── fake_server.dart │ │ │ ├── labellab_api.dart │ │ │ └── labellab_api_impl.dart │ │ └── repository.dart │ ├── labellab_app.dart │ ├── main.dart │ ├── model │ │ ├── auth_user.dart │ │ ├── classification.dart │ │ ├── classification_label.dart │ │ ├── comment.dart │ │ ├── group.dart │ │ ├── image.dart │ │ ├── issue.dart │ │ ├── label.dart │ │ ├── label_selection.dart │ │ ├── location.dart │ │ ├── log.dart │ │ ├── mapper │ │ │ ├── issue_mapper.dart │ │ │ └── ml_model_mapper.dart │ │ ├── member.dart │ │ ├── message.dart │ │ ├── ml_model.dart │ │ ├── project.dart │ │ ├── register_user.dart │ │ ├── team.dart │ │ ├── team_member.dart │ │ ├── upload_image.dart │ │ └── user.dart │ ├── routing │ │ ├── application.dart │ │ ├── route_handler.dart │ │ └── routes.dart │ ├── screen │ │ ├── backend_selection │ │ │ ├── backend_selection_screen.dart │ │ │ ├── backend_service_selector.dart │ │ │ └── init_screen.dart │ │ ├── classification │ │ │ ├── classification_bloc.dart │ │ │ ├── classification_screen.dart │ │ │ └── classification_state.dart │ │ ├── classify │ │ │ ├── classify_bloc.dart │ │ │ ├── classify_screen.dart │ │ │ └── classify_state.dart │ │ ├── history │ │ │ ├── history_bloc.dart │ │ │ ├── history_item.dart │ │ │ ├── history_screen.dart │ │ │ ├── history_search_screen.dart │ │ │ └── history_state.dart │ │ ├── home │ │ │ ├── camera_button.dart │ │ │ ├── home_screen.dart │ │ │ ├── nav_item.dart │ │ │ └── user_detail_loading.dart │ │ ├── issue │ │ │ ├── add_edit │ │ │ │ └── add_edit_issue_screen.dart │ │ │ ├── details │ │ │ │ ├── issue_details_bloc.dart │ │ │ │ ├── issue_details_screen.dart │ │ │ │ ├── issue_details_state.dart │ │ │ │ └── local_widget.dart │ │ │ │ │ └── expnasion_tile.dart │ │ │ └── issue_activity │ │ │ │ ├── issue_activity_bloc.dart │ │ │ │ ├── issue_activity_screen.dart │ │ │ │ ├── issue_activity_state.dart │ │ │ │ └── local_widgets │ │ │ │ └── filter_issue_sheet.dart │ │ ├── login │ │ │ ├── github_signin_screen.dart │ │ │ └── login_screen.dart │ │ ├── main_screen.dart │ │ ├── profile │ │ │ ├── edit_info │ │ │ │ └── edit_info_screen.dart │ │ │ ├── profile_bloc.dart │ │ │ ├── profile_screen.dart │ │ │ ├── profile_state.dart │ │ │ └── update_password │ │ │ │ └── update_password_screen.dart │ │ ├── project │ │ │ ├── add_edit │ │ │ │ └── add_edit_project_screen.dart │ │ │ ├── add_edit_group │ │ │ │ └── add_edit_group.dart │ │ │ ├── add_edit_label │ │ │ │ └── add_edit_label_dialog.dart │ │ │ ├── add_edit_model │ │ │ │ └── add_edit_model_dialog.dart │ │ │ ├── add_member │ │ │ │ ├── project_add_member_bloc.dart │ │ │ │ ├── project_add_member_screen.dart │ │ │ │ └── project_add_member_state.dart │ │ │ ├── add_team_dialog │ │ │ │ └── add_team_dialog.dart │ │ │ ├── chat │ │ │ │ ├── chat_screen.dart │ │ │ │ ├── chat_screen_bloc.dart │ │ │ │ ├── chat_screen_state.dart │ │ │ │ └── local_widgets │ │ │ │ │ ├── message_bubble.dart │ │ │ │ │ ├── message_input.dart │ │ │ │ │ └── messages_list.dart │ │ │ ├── common │ │ │ │ ├── label_selection_list.dart │ │ │ │ └── label_selection_painter.dart │ │ │ ├── detail │ │ │ │ ├── project_detail_bloc.dart │ │ │ │ ├── project_detail_screen.dart │ │ │ │ └── project_detail_state.dart │ │ │ ├── label_tool │ │ │ │ ├── label_tool_bloc.dart │ │ │ │ ├── label_tool_screen.dart │ │ │ │ └── label_tool_state.dart │ │ │ ├── ml_model │ │ │ │ └── history │ │ │ │ │ ├── model_history_bloc.dart │ │ │ │ │ ├── model_history_screen.dart │ │ │ │ │ └── model_history_state.dart │ │ │ ├── project_activity │ │ │ │ ├── local_widgets │ │ │ │ │ ├── filter_bottom_sheet.dart │ │ │ │ │ └── filter_dropdown.dart │ │ │ │ ├── project_activity_bloc.dart │ │ │ │ ├── project_activity_screen.dart │ │ │ │ └── project_activity_state.dart │ │ │ ├── project_bloc.dart │ │ │ ├── project_item.dart │ │ │ ├── project_screen.dart │ │ │ ├── project_search_screen.dart │ │ │ ├── project_state.dart │ │ │ ├── team_details │ │ │ │ ├── local_widgets │ │ │ │ │ └── add_team_member_dialog.dart │ │ │ │ ├── team_details_bloc.dart │ │ │ │ ├── team_details_screen.dart │ │ │ │ └── team_details_state.dart │ │ │ ├── upload_image │ │ │ │ ├── project_upload_image_bloc.dart │ │ │ │ ├── project_upload_image_screen.dart │ │ │ │ └── project_upload_image_state.dart │ │ │ ├── view_group │ │ │ │ ├── add_images │ │ │ │ │ ├── group_add_images_bloc.dart │ │ │ │ │ ├── group_add_images_screen.dart │ │ │ │ │ └── group_add_images_state.dart │ │ │ │ ├── project_view_group_bloc.dart │ │ │ │ ├── project_view_group_screen.dart │ │ │ │ └── project_view_group_state.dart │ │ │ ├── view_image │ │ │ │ ├── project_view_image_bloc.dart │ │ │ │ ├── project_view_image_screen.dart │ │ │ │ └── project_view_image_state.dart │ │ │ ├── view_image_path │ │ │ │ ├── project_image_path_bloc.dart │ │ │ │ ├── project_image_path_screen.dart │ │ │ │ └── project_image_path_state.dart │ │ │ └── view_more_images │ │ │ │ ├── project_more_images_bloc.dart │ │ │ │ ├── project_more_images_screen.dart │ │ │ │ └── project_more_images_state.dart │ │ ├── sign_up │ │ │ └── sign_up_screen.dart │ │ └── train │ │ │ ├── dialogs │ │ │ ├── add_class_dialog.dart │ │ │ ├── add_layer_dialog.dart │ │ │ ├── add_step_dialog.dart │ │ │ └── dto │ │ │ │ ├── layer_dto.dart │ │ │ │ ├── model_dto.dart │ │ │ │ └── step_dto.dart │ │ │ ├── model_train_bloc.dart │ │ │ ├── model_train_screen.dart │ │ │ └── model_train_state.dart │ ├── state │ │ └── auth_state.dart │ ├── util │ │ └── util.dart │ └── widgets │ │ ├── color_box.dart │ │ ├── custom_dropdown.dart │ │ ├── delete_confirm_dialog.dart │ │ ├── empty_placeholder.dart │ │ ├── group_item.dart │ │ ├── issue_list_tile.dart │ │ ├── label_icon_button.dart │ │ ├── label_text_field.dart │ │ ├── label_text_form_field.dart │ │ ├── leave_project_confirm_dialog.dart │ │ ├── line_chart.dart │ │ ├── recent_activity_list_tile.dart │ │ ├── selected_image.dart │ │ └── team_item.dart ├── pubspec.yaml ├── screenshots │ ├── add_image │ │ ├── ss_1.png │ │ ├── ss_2.png │ │ └── ss_3.png │ ├── classification │ │ ├── ss_1.png │ │ └── ss_2.png │ ├── create_label │ │ ├── ss_1.png │ │ └── ss_2.png │ ├── create_project │ │ ├── ss_1.png │ │ ├── ss_2.png │ │ └── ss_3.png │ ├── edit_image │ │ ├── ss_1.png │ │ ├── ss_2.png │ │ └── ss_3.png │ ├── image_path │ │ ├── ss_1.png │ │ └── ss_2.png │ ├── initial │ │ ├── ss_1.png │ │ └── ss_2.png │ ├── label_image │ │ ├── ss_1.png │ │ ├── ss_2.png │ │ ├── ss_3.png │ │ └── ss_4.png │ └── sign_in │ │ ├── ss_1.png │ │ └── ss_2.png └── test │ ├── classifications_test.dart │ ├── comment_test.dart │ ├── images_test.dart │ ├── issue_screen_test │ └── create_issue_test.dart │ ├── issue_test.dart │ ├── labels_test.dart │ ├── login_screen_test.dart │ ├── logs_test.dart │ ├── mock_labellab_api.dart │ ├── mock_labellab_api_impl.dart │ ├── profile_test.dart │ ├── project_test.dart │ ├── sign_up_screen_test.dart │ ├── teams_test.dart │ ├── train_test.dart │ └── wrapper │ └── material_wrapper.dart ├── package.json ├── pyproject.toml ├── reference ├── Design.png ├── Labellab-ER.mwb ├── Labellab-sql-script.sql ├── images │ ├── back-skip.png │ ├── bounding-box.png │ ├── edit-elephant-1.png │ ├── labeller.png │ ├── labels.png │ ├── polygon.png │ ├── shortcut.png │ ├── sidebar.png │ └── watch.png └── labellab.v2.yaml └── static.json /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/workflows/Flutter-CI.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | paths: 4 | - 'labellab_mobile/**' 5 | name: Test, Build and Release apk 6 | 7 | jobs: 8 | build: 9 | name: Build APK 10 | runs-on: ubuntu-latest 11 | 12 | defaults: 13 | run: 14 | working-directory: ./labellab_mobile 15 | 16 | steps: 17 | - uses: actions/checkout@v1 18 | - uses: actions/setup-java@v1 19 | with: 20 | java-version: '12.x' 21 | - uses: subosito/flutter-action@v1 22 | with: 23 | flutter-version: '3.0.1' 24 | 25 | - run: flutter clean 26 | - run: flutter pub get 27 | 28 | # - run: flutter format --set-exit-if-changed . 29 | 30 | 31 | # Test case are failing flutter SDk 32 | # - run: flutter test 33 | 34 | # Build APk (Some issue here) 35 | # - run: flutter build apk 36 | # - run: flutter build apk --debug --split-per-abi 37 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "prettier.jsxSingleQuote": true, 3 | "prettier.semi": false, 4 | "prettier.singleQuote": true 5 | } -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | 3 | services: 4 | 5 | flask_server: 6 | build: ./labellab-flask 7 | working_dir: /usr/labellab/labellab-flask 8 | ports: 9 | - 5000:5000 10 | volumes: 11 | - ./labellab-flask:/usr/labellab/labellab-flask 12 | restart: always 13 | links: 14 | - mysql:dbserver 15 | environment: 16 | FLASK_ENV: development 17 | 18 | mysql: 19 | image: "mysql/mysql-server:5.7" 20 | restart: always 21 | 22 | client: 23 | build: ./labellab-client 24 | working_dir: /usr/labellab/labellab-client 25 | ports: 26 | - 3000:3000 27 | volumes: 28 | - ./labellab-client/:/usr/labellab/labellab-client 29 | environment: 30 | - NODE_ENV=development 31 | -------------------------------------------------------------------------------- /labellab-client/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | npm-debug.log 3 | Dockerfile* 4 | docker-compose* 5 | .dockerignore 6 | .git 7 | .gitignore 8 | .env 9 | */bin 10 | */obj 11 | README.md 12 | LICENSE 13 | .vscode -------------------------------------------------------------------------------- /labellab-client/.env.example: -------------------------------------------------------------------------------- 1 | REACT_APP_HOST= 2 | REACT_APP_SERVER_ENVIRONMENT= 3 | REACT_APP_SERVER_PORT= 4 | REACT_APP_GOOGLE_CLIENT_ID= 5 | REACT_APP_GOOGLE_MAPS_API_KEY= 6 | -------------------------------------------------------------------------------- /labellab-client/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | browser: true, 4 | commonjs: true, 5 | es6: true 6 | }, 7 | extends: [ 8 | 'eslint:recommended', 9 | 'plugin:react/recommended', 10 | 'react-app', 11 | 'plugin:prettier/recommended', 12 | 'prettier/react' 13 | ], 14 | parser: 'babel-eslint', 15 | parserOptions: { 16 | ecmaVersion: 2018, 17 | sourceType: 'module' 18 | }, 19 | rules: { 20 | 'no-unused-vars': [ 21 | 'off', 22 | { vars: 'all', args: 'after-used', ignoreRestSiblings: false } 23 | ], 24 | 'no-console': 'off', 25 | 'prettier/prettier': ['warn', { semi: false, singleQuote: true }], 26 | "react/prop-types": 0 27 | }, 28 | settings: { 29 | react: { 30 | createClass: 'createReactClass', 31 | pragma: 'React', 32 | version: 'detect', 33 | flowVersion: '0.53' 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /labellab-client/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /labellab-client/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:8 2 | 3 | RUN mkdir -p /usr/labellab/labellab-client 4 | WORKDIR /usr/labellab/labellab-client 5 | 6 | ENV PATH /usr/app/node_modules/.bin:$PATH 7 | 8 | 9 | COPY package.json /usr/labellab/labellab-client 10 | RUN npm install --silent 11 | 12 | EXPOSE 3000 13 | CMD ["npm", "start"] -------------------------------------------------------------------------------- /labellab-client/config/jest/cssTransform.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // This is a custom Jest transformer turning style imports into empty objects. 4 | // http://facebook.github.io/jest/docs/en/webpack.html 5 | 6 | module.exports = { 7 | process() { 8 | return 'module.exports = {};'; 9 | }, 10 | getCacheKey() { 11 | // The output is always the same. 12 | return 'cssTransform'; 13 | }, 14 | }; 15 | -------------------------------------------------------------------------------- /labellab-client/config/pnpTs.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const { resolveModuleName } = require('ts-pnp'); 4 | 5 | exports.resolveModuleName = ( 6 | typescript, 7 | moduleName, 8 | containingFile, 9 | compilerOptions, 10 | resolutionHost 11 | ) => { 12 | return resolveModuleName( 13 | moduleName, 14 | containingFile, 15 | compilerOptions, 16 | resolutionHost, 17 | typescript.resolveModuleName 18 | ); 19 | }; 20 | 21 | exports.resolveTypeReferenceDirective = ( 22 | typescript, 23 | moduleName, 24 | containingFile, 25 | compilerOptions, 26 | resolutionHost 27 | ) => { 28 | return resolveModuleName( 29 | moduleName, 30 | containingFile, 31 | compilerOptions, 32 | resolutionHost, 33 | typescript.resolveTypeReferenceDirective 34 | ); 35 | }; 36 | -------------------------------------------------------------------------------- /labellab-client/prettier.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | semi: false, 3 | singleQuote: true 4 | } 5 | -------------------------------------------------------------------------------- /labellab-client/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scorelab/LabelLab/080a7cc7fa5a32b042535b1e1214b60bf5881501/labellab-client/public/favicon.ico -------------------------------------------------------------------------------- /labellab-client/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": ".", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /labellab-client/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | animation: App-logo-spin infinite 20s linear; 7 | height: 40vmin; 8 | pointer-events: none; 9 | } 10 | 11 | .App-header { 12 | background-color: #282c34; 13 | min-height: 100vh; 14 | display: flex; 15 | flex-direction: column; 16 | align-items: center; 17 | justify-content: center; 18 | font-size: calc(10px + 2vmin); 19 | color: white; 20 | } 21 | 22 | .App-link { 23 | color: #61dafb; 24 | } 25 | 26 | @keyframes App-logo-spin { 27 | from { 28 | transform: rotate(0deg); 29 | } 30 | to { 31 | transform: rotate(360deg); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /labellab-client/src/App.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import AppIndex from './components/index' 3 | import './App.css' 4 | 5 | export default class App extends Component { 6 | render() { 7 | return 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /labellab-client/src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom' 3 | import App from './App' 4 | 5 | it('renders without crashing', () => { 6 | setTimeout(() => { 7 | const div = document.createElement('div') 8 | ReactDOM.render(, div) 9 | ReactDOM.unmountComponentAtNode(div) 10 | }) 11 | }) 12 | -------------------------------------------------------------------------------- /labellab-client/src/__tests__/reducers/registerReducer.test.js: -------------------------------------------------------------------------------- 1 | import { 2 | REGISTER_FAILURE, 3 | REGISTER_REQUEST, 4 | REGISTER_SUCCESS 5 | } from "../../constants/index"; 6 | import register from "../../reducers/register"; 7 | 8 | const initState = { 9 | isRegistering: false, 10 | error: false, 11 | errField: '', 12 | statusText: '' 13 | } 14 | 15 | describe("Register Reducer", () => { 16 | it("Should return the default state", () => { 17 | const newState = register(undefined, {}); 18 | expect(newState).toEqual(initState); 19 | }); 20 | it("Should send a register request", () => { 21 | const newState = register(initState, { 22 | type: REGISTER_REQUEST 23 | }); 24 | expect(newState).toEqual({ 25 | ...initState, 26 | isRegistering: true, 27 | error: false 28 | }); 29 | }); 30 | it("Should register a user", () => { 31 | const mockPayload = { statusText: "OK" } 32 | const newState = register(initState, { 33 | type: REGISTER_SUCCESS, 34 | payload: mockPayload 35 | }); 36 | expect(newState).toEqual({ 37 | ...initState, 38 | isRegistering: false, 39 | statusText: mockPayload, 40 | error: false 41 | }); 42 | }); 43 | }); -------------------------------------------------------------------------------- /labellab-client/src/actions/index.js: -------------------------------------------------------------------------------- 1 | export * from './auth' 2 | export * from './register' 3 | export * from './user' 4 | export * from './project/index' 5 | export * from './label' 6 | export * from './image' 7 | export * from './issue' 8 | export * from './analytics' 9 | export * from './model' 10 | export * from './notification' 11 | -------------------------------------------------------------------------------- /labellab-client/src/actions/project/pathTracking.js: -------------------------------------------------------------------------------- 1 | import { 2 | FETCH_COORDINATES_FAILURE, 3 | FETCH_COORDINATES_REQUEST, 4 | FETCH_COORDINATES_SUCCESS 5 | } from '../../constants/index' 6 | 7 | import FetchApi from '../../utils/FetchAPI' 8 | 9 | export const fetchCoordinates = (projectId) => { 10 | return dispatch => { 11 | dispatch(request()) 12 | FetchApi.get('/api/v1/project/polylines/' + projectId) 13 | .then(res => { 14 | dispatch(success(res.data.body)) 15 | }) 16 | .catch(err => { 17 | if (err.response) { 18 | err.response.data 19 | ? dispatch(failure(err.response.data.msg)) 20 | : dispatch(failure(err.response.statusText, null)) 21 | } 22 | }) 23 | } 24 | function request() { 25 | return { type: FETCH_COORDINATES_REQUEST } 26 | } 27 | function success(data) { 28 | return { type: FETCH_COORDINATES_SUCCESS, payload: data } 29 | } 30 | function failure(error) { 31 | return { type: FETCH_COORDINATES_FAILURE, payload: error } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /labellab-client/src/actions/project/search.js: -------------------------------------------------------------------------------- 1 | import { SEARCH_PROJECTS, SEARCH_PROJECTS_FAILURE } from '../../constants/index' 2 | 3 | import FetchApi from '../../utils/FetchAPI' 4 | 5 | export const getSearchProjects = query => { 6 | return dispatch => { 7 | if (!query) { 8 | query = 'null' 9 | } 10 | FetchApi('GET', '/api/v1/project/search/' + query, null, true) 11 | .then(response => { 12 | dispatch(success(response.data.body)) 13 | }) 14 | .catch(err => { 15 | if (err.response) { 16 | err.response.data 17 | ? dispatch( 18 | failure(err.response.data.msg, err.response.data.err_field) 19 | ) 20 | : dispatch(failure(err.response.statusText, null)) 21 | } 22 | }) 23 | } 24 | function success(data) { 25 | return { type: SEARCH_PROJECTS, payload: data } 26 | } 27 | function failure(error) { 28 | return { type: SEARCH_PROJECTS_FAILURE, payload: error } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /labellab-client/src/actions/register.js: -------------------------------------------------------------------------------- 1 | import { 2 | REGISTER_REQUEST, 3 | REGISTER_SUCCESS, 4 | REGISTER_FAILURE 5 | } from '../constants/index' 6 | 7 | import FetchApi from '../utils/FetchAPI' 8 | 9 | export const userRegister = (data, callback) => { 10 | return dispatch => { 11 | dispatch(request()) 12 | FetchApi.post('/api/v1/auth/register', data) 13 | .then(() => { 14 | dispatch(success()) 15 | callback() 16 | }) 17 | .catch(err => { 18 | if (err.response) { 19 | err.response.data 20 | ? dispatch( 21 | failure(err.response.data.msg, err.response.data.err_field) 22 | ) 23 | : dispatch(failure(err.response.statusText, null)) 24 | } 25 | }) 26 | } 27 | function request() { 28 | return { type: REGISTER_REQUEST } 29 | } 30 | function success() { 31 | return { type: REGISTER_SUCCESS, payload: 'Please log in to continue.' } 32 | } 33 | function failure(error, other) { 34 | return { type: REGISTER_FAILURE, payload: error, other: other } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /labellab-client/src/components/dashboard/css/dashboard.css: -------------------------------------------------------------------------------- 1 | .dashboard-parent { 2 | height: 100% !important; 3 | width: 100%; 4 | background: #e5e5e5; 5 | min-height: 100vh !important; 6 | } 7 | 8 | .dashboard-container { 9 | width: 80%; 10 | margin: auto; 11 | } 12 | 13 | .create-project-button { 14 | padding: 2em 0; 15 | } 16 | 17 | .modal-actions { 18 | display: flex; 19 | flex-direction: column; 20 | align-items: center; 21 | } 22 | 23 | .modal-actions > div { 24 | padding-top: 1.5em; 25 | } 26 | 27 | .modal-actions:last-child { 28 | display: block; 29 | text-align: center; 30 | padding-bottom: 1.5em; 31 | } 32 | 33 | /* Added padding for the mobile view between the title and the card */ 34 | @media only screen and (max-width: 768px) { 35 | .mobile-padding { 36 | padding-bottom: 10px !important; 37 | } 38 | 39 | .create-button { 40 | width: 100%; 41 | color: white !important; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /labellab-client/src/components/dashboard/css/previous.css: -------------------------------------------------------------------------------- 1 | .previous-card-image { 2 | width: 100% !important; 3 | } 4 | 5 | .card-headers .header { 6 | width: 100%; 7 | overflow-wrap: break-word; 8 | } 9 | -------------------------------------------------------------------------------- /labellab-client/src/components/error/css/notfound.css: -------------------------------------------------------------------------------- 1 | .main { 2 | height: 50vh; 3 | display: flex; 4 | justify-content: center; 5 | align-items: center; 6 | } 7 | .heading { 8 | display: flex; 9 | flex-direction: row; 10 | justify-content: center; 11 | font-size: 5em; 12 | 13 | } 14 | .green { 15 | color: green 16 | } -------------------------------------------------------------------------------- /labellab-client/src/components/error/notFound.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import { Link } from 'react-router-dom' 3 | import { Header, Button } from 'semantic-ui-react' 4 | import './css/notfound.css' 5 | class NotFound extends Component { 6 | render() { 7 | return ( 8 |
9 |
10 | 11 |
12 |
4
13 |
0
14 |
4
15 |
16 |
17 |
18 |
19 |
20 |
21 | 22 | 25 | 26 | 27 |
28 |
29 | ) 30 | } 31 | } 32 | 33 | export default NotFound 34 | -------------------------------------------------------------------------------- /labellab-client/src/components/error/unauthorized.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import { Link } from 'react-router-dom' 3 | import { Header, Button } from 'semantic-ui-react' 4 | import './css/notfound.css' 5 | class Unauthorized extends Component { 6 | render() { 7 | return ( 8 |
9 |
10 | 11 |
12 |
4
13 |
0
14 |
1
15 |
16 |
17 |
18 |
19 |
20 |
21 | 22 | 25 | 26 | 27 |
28 |
29 | ) 30 | } 31 | } 32 | 33 | export default Unauthorized 34 | -------------------------------------------------------------------------------- /labellab-client/src/components/labeller/CalcBoundsHOC.js: -------------------------------------------------------------------------------- 1 | import React, { PureComponent, forwardRef } from 'react' 2 | import { CRS, LatLngBounds } from 'leaflet' 3 | 4 | export const maxZoom = 7 5 | export function withBounds(Comp) { 6 | class CalcBoundsLayer extends PureComponent { 7 | calcBounds() { 8 | const crs = CRS.Simple 9 | const { height, width } = this.props 10 | 11 | if (!height || !width) return null 12 | 13 | const southWest = crs.unproject({ x: 0, y: height }, maxZoom - 1) 14 | const northEast = crs.unproject({ x: width, y: 0 }, maxZoom - 1) 15 | const bounds = new LatLngBounds(southWest, northEast) 16 | 17 | return bounds 18 | } 19 | 20 | render() { 21 | const { forwardedRef, ...rest } = this.props 22 | const bounds = this.calcBounds() 23 | if (!bounds) return null 24 | return 25 | } 26 | } 27 | 28 | function exp(props, ref) { 29 | return 30 | } 31 | return forwardRef(exp) 32 | } -------------------------------------------------------------------------------- /labellab-client/src/components/labeller/css/LabelingApp.css: -------------------------------------------------------------------------------- 1 | .leaflet-container { 2 | height: 100%; 3 | width: 100%; 4 | } 5 | 6 | html, 7 | body, 8 | #root > *, 9 | .ui.grid { 10 | height: 100%; 11 | min-height: 100%; 12 | } 13 | 14 | .leaflet-container { 15 | cursor: inherit !important; 16 | } 17 | 18 | .item.disabled { 19 | opacity: 0.5; 20 | } 21 | 22 | .vertex.editing.finished { 23 | cursor: move !important; 24 | } 25 | 26 | .midpoint { 27 | cursor: copy !important; 28 | } 29 | 30 | .vertex:not(.finished).first { 31 | cursor: cell !important; 32 | } 33 | -------------------------------------------------------------------------------- /labellab-client/src/components/loading/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import { connect } from 'react-redux' 3 | 4 | class Loading extends Component { 5 | render() { 6 | return
Loading........
7 | } 8 | } 9 | 10 | export default connect( 11 | null, 12 | null 13 | )(Loading) 14 | -------------------------------------------------------------------------------- /labellab-client/src/components/login/css/ForgotPassword.css: -------------------------------------------------------------------------------- 1 | .emailForm { 2 | display: flex; 3 | justify-content: center; 4 | } 5 | 6 | .mainBody { 7 | text-align: center; 8 | margin-top: 9rem; 9 | } 10 | 11 | .sendMail { 12 | margin-left: 20px; 13 | } 14 | 15 | .btn-home { 16 | margin: 20px auto !important; 17 | } 18 | 19 | @media only screen and (max-width: 767px) { 20 | .emailForm { 21 | flex-direction: column; 22 | margin-left: 40px; 23 | margin-right: 40px; 24 | } 25 | 26 | .sendMail { 27 | margin-left: 0; 28 | margin-top: 20px; 29 | } 30 | } 31 | 32 | .error-msg { 33 | text-align: left; 34 | margin: 2px 0px; 35 | color: #9f3a38; 36 | font-weight: 500; 37 | } 38 | -------------------------------------------------------------------------------- /labellab-client/src/components/login/css/ResetPassword.css: -------------------------------------------------------------------------------- 1 | .errorResettingPassword{ 2 | 3 | } 4 | .successBody{ 5 | text-align: center; 6 | margin-top: 8rem; 7 | } 8 | .failureBody{ 9 | text-align: center; 10 | margin-top: 8rem; 11 | } -------------------------------------------------------------------------------- /labellab-client/src/components/login/css/login.css: -------------------------------------------------------------------------------- 1 | @media only screen and (max-width: 600px) { 2 | .login-parent { 3 | width: 80% !important; 4 | } 5 | } 6 | 7 | .login-grand-parent { 8 | display: flex; 9 | flex-direction: column; 10 | height: 100vh; 11 | } 12 | 13 | .login-parent { 14 | margin-top: 5em; 15 | width: 30%; 16 | margin-left: auto; 17 | margin-right: auto; 18 | } 19 | 20 | .login-oauth-icon { 21 | display: flex; 22 | justify-content: space-evenly; 23 | margin: 2em 0 2em; 24 | } 25 | 26 | .login-oauth-icon div { 27 | max-width: 15vw; 28 | } 29 | 30 | .login-icons { 31 | width: 45px; 32 | } 33 | 34 | .action { 35 | padding: 1em 0; 36 | } 37 | 38 | .login-form { 39 | margin-top: 2em; 40 | } 41 | 42 | .github-login { 43 | width: 11vw; 44 | height: 3rem; 45 | background: black; 46 | opacity: 0.6; 47 | color: white; 48 | box-shadow: 0px 1px 4px black; 49 | } -------------------------------------------------------------------------------- /labellab-client/src/components/logout/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import { connect } from 'react-redux' 3 | import PropTypes from 'prop-types' 4 | import { logout } from '../../actions/index' 5 | class Logout extends Component { 6 | componentDidMount() { 7 | this.props.logout(this.callback) 8 | } 9 | callback = () => { 10 | this.props.history.push('/login') 11 | } 12 | render() { 13 | return <> 14 | } 15 | } 16 | 17 | Logout.propTypes = { 18 | history: PropTypes.object, 19 | logout: PropTypes.func 20 | } 21 | 22 | const mapActionToProps = dispatch => { 23 | return { 24 | logout: callback => { 25 | return dispatch(logout(callback)) 26 | } 27 | } 28 | } 29 | 30 | export default connect( 31 | null, 32 | mapActionToProps 33 | )(Logout) 34 | -------------------------------------------------------------------------------- /labellab-client/src/components/model-editor/css/classifierEditor.css: -------------------------------------------------------------------------------- 1 | .classifier-column-heading { 2 | text-align: center; 3 | } -------------------------------------------------------------------------------- /labellab-client/src/components/model-editor/css/modelEditor.css: -------------------------------------------------------------------------------- 1 | .model-editor { 2 | display: flex; 3 | flex-direction: column; 4 | margin: auto; 5 | padding-top: 1em; 6 | width: 95%; 7 | } -------------------------------------------------------------------------------- /labellab-client/src/components/model-editor/sub-modules/css/addModelEntityModal.css: -------------------------------------------------------------------------------- 1 | .add-entity-modal { 2 | align-items: center; 3 | display: flex; 4 | flex-direction: column; 5 | } 6 | 7 | .entity-settings { 8 | display: flex; 9 | flex-direction: row; 10 | justify-content: space-around; 11 | margin: 1em; 12 | flex-wrap: wrap; 13 | } 14 | 15 | .entity-settings-option { 16 | margin: 0.5em; 17 | } 18 | -------------------------------------------------------------------------------- /labellab-client/src/components/model-editor/sub-modules/css/customBuilder.css: -------------------------------------------------------------------------------- 1 | .custom-card { 2 | text-align: center; 3 | } 4 | 5 | .question-icon { 6 | cursor: pointer; 7 | padding: 1em; 8 | } 9 | 10 | .layer-label-container { 11 | align-items: center; 12 | background-color: #e8e8e8; 13 | border-radius: 5px; 14 | display: flex; 15 | font-weight: 600; 16 | justify-content: space-between; 17 | margin-bottom: 0.4em; 18 | padding: 0.5rem; 19 | width: 100%; 20 | } 21 | 22 | .layer-delete-icon { 23 | align-self: flex-end; 24 | cursor: pointer; 25 | padding-left: 0.2em; 26 | } 27 | 28 | .layer-edit-icon { 29 | cursor: pointer; 30 | padding-left: 0.5em; 31 | } 32 | -------------------------------------------------------------------------------- /labellab-client/src/components/model-editor/sub-modules/css/exporter.css: -------------------------------------------------------------------------------- 1 | .exporter-card { 2 | text-align: center; 3 | } -------------------------------------------------------------------------------- /labellab-client/src/components/model-editor/sub-modules/css/labelSelector.css: -------------------------------------------------------------------------------- 1 | .add-new-label-btn { 2 | padding-top: 1em; 3 | } 4 | 5 | .label-card { 6 | padding: 1em; 7 | text-align: left; 8 | } 9 | 10 | .label-header-row { 11 | margin-left: 0.5em; 12 | margin-right: 0.5em; 13 | margin-top: 0.3em; 14 | margin-bottom: -1em; 15 | flex-direction: row; 16 | justify-content: space-between; 17 | align-items: center; 18 | } 19 | 20 | .label-name { 21 | color: #393939; 22 | font-size: 1.6em; 23 | display: inline; 24 | } 25 | 26 | .label-type-icon { 27 | padding-left: 0.5em; 28 | } 29 | 30 | .label-delete-icon { 31 | float: right; 32 | } 33 | 34 | .label-count { 35 | align-self: flex-end; 36 | margin: 0.5em; 37 | } 38 | 39 | .label-images { 40 | display: flex; 41 | align-items: center; 42 | justify-content: flex-start; 43 | width: 95%; 44 | margin: auto; 45 | overflow-x: scroll; 46 | } 47 | 48 | .label-images::-webkit-scrollbar { 49 | display: none; 50 | } 51 | 52 | .label-image { 53 | border-radius: 5px; 54 | height: 100px; 55 | margin-left: 1em; 56 | width: auto; 57 | } 58 | -------------------------------------------------------------------------------- /labellab-client/src/components/model-editor/sub-modules/css/modelTester.css: -------------------------------------------------------------------------------- 1 | .model-tester-card { 2 | text-align: center; 3 | } 4 | 5 | .inputfile { 6 | width: 0.1px; 7 | height: 0.1px; 8 | opacity: 0; 9 | overflow: hidden; 10 | position: absolute; 11 | z-index: -1; 12 | } 13 | 14 | .progress-bar-list { 15 | display: 'flex'; 16 | flex-direction: 'column'; 17 | width: 100%; 18 | } 19 | 20 | .test-card-top { 21 | padding-left: 0.6em; 22 | padding-right: 0.6em; 23 | display: flex; 24 | align-items: center; 25 | justify-content: space-between; 26 | } 27 | 28 | .preview-image { 29 | max-height: 8em; 30 | max-width: 10em; 31 | } -------------------------------------------------------------------------------- /labellab-client/src/components/model-editor/sub-modules/css/preprocessingSelector.css: -------------------------------------------------------------------------------- 1 | .preprocessing-card { 2 | text-align: left; 3 | } 4 | 5 | .preprocessing-card-header-row { 6 | display: flex; 7 | flex-direction: row; 8 | justify-content: center; 9 | align-items: center; 10 | margin-bottom: -1em; 11 | } 12 | 13 | .preprocessing-card-header { 14 | width: 100%; 15 | text-align: center; 16 | } 17 | 18 | .preprocessing-card-add-btn { 19 | margin-top: -1em; 20 | margin-left: auto; 21 | } 22 | 23 | .preprocessing-card-bottom-row { 24 | margin-top: -1em; 25 | } 26 | 27 | .preprocessing-step-label { 28 | display: inline-block; 29 | margin-top: 0.4em; 30 | margin-right: 0.4em; 31 | } 32 | 33 | .step-delete-icon { 34 | cursor: pointer; 35 | padding-left: 0.2em; 36 | } 37 | 38 | .step-edit-icon { 39 | cursor: pointer; 40 | padding-left: 0.5em; 41 | } 42 | -------------------------------------------------------------------------------- /labellab-client/src/components/model-editor/sub-modules/css/trainingGraphs.css: -------------------------------------------------------------------------------- 1 | .training-graphs-card { 2 | text-align: center; 3 | } 4 | 5 | .training-graphs { 6 | display: flex; 7 | align-items: center; 8 | justify-content: space-evenly; 9 | overflow-x: scroll; 10 | } 11 | 12 | .training-graphs::-webkit-scrollbar { 13 | display: none; 14 | } 15 | 16 | .training-graph { 17 | height: 10em; 18 | width: auto; 19 | } 20 | 21 | .training-results { 22 | display: flex; 23 | align-items: center; 24 | justify-content: space-evenly; 25 | } 26 | -------------------------------------------------------------------------------- /labellab-client/src/components/model-editor/sub-modules/css/transferLearningBuilder.css: -------------------------------------------------------------------------------- 1 | .transfer-learning-card { 2 | text-align: center; 3 | } 4 | 5 | .question-icon { 6 | cursor: pointer; 7 | padding: 1em; 8 | } 9 | 10 | .layer-label-container { 11 | align-items: center; 12 | background-color: #e8e8e8; 13 | border-radius: 5px; 14 | display: flex; 15 | font-weight: 600; 16 | justify-content: space-between; 17 | margin-bottom: 0.4em; 18 | padding: 0.5rem; 19 | width: 100%; 20 | } 21 | 22 | .layer-delete-icon { 23 | align-self: flex-end; 24 | cursor: pointer; 25 | padding-left: 0.2em; 26 | } 27 | 28 | .layer-edit-icon { 29 | cursor: pointer; 30 | padding-left: 0.5em; 31 | } 32 | -------------------------------------------------------------------------------- /labellab-client/src/components/model-editor/sub-modules/css/uploadBuilder.css: -------------------------------------------------------------------------------- 1 | .upload-model-card { 2 | text-align: center; 3 | } 4 | 5 | .question-icon { 6 | cursor: pointer; 7 | padding: 1em; 8 | } 9 | 10 | .inputfile { 11 | width: 0.1px; 12 | height: 0.1px; 13 | opacity: 0; 14 | overflow: hidden; 15 | position: absolute; 16 | z-index: -1; 17 | } -------------------------------------------------------------------------------- /labellab-client/src/components/model-editor/sub-modules/options/lossOptions.js: -------------------------------------------------------------------------------- 1 | const lossOptions = ['Binary Cross Entropy', 'Categorical Cross Entropy'] 2 | 3 | export default lossOptions 4 | -------------------------------------------------------------------------------- /labellab-client/src/components/model-editor/sub-modules/options/metricOptions.js: -------------------------------------------------------------------------------- 1 | const metricOptions = ['Accuracy'] 2 | 3 | export default metricOptions 4 | -------------------------------------------------------------------------------- /labellab-client/src/components/model-editor/sub-modules/options/optimizerOptions.js: -------------------------------------------------------------------------------- 1 | const optimizerOptions = [ 2 | 'Adadelta', 3 | 'Adagrad', 4 | 'Adam', 5 | 'Adamax', 6 | 'Ftrl', 7 | 'Nadam', 8 | 'RMSProp', 9 | 'SGD' 10 | ] 11 | 12 | export default optimizerOptions 13 | -------------------------------------------------------------------------------- /labellab-client/src/components/model-editor/sub-modules/options/transferLearningOptions.js: -------------------------------------------------------------------------------- 1 | const transferLearningOptions = [ 2 | 'DenseNet121', 3 | 'DenseNet169', 4 | 'DenseNet201', 5 | 'InceptionResNetV2', 6 | 'InceptionV3', 7 | 'MobileNet', 8 | 'MobileNetV2', 9 | 'NASNetLarge', 10 | 'NASNetMobile', 11 | 'ResNet50', 12 | 'ResNet101', 13 | 'ResNet152', 14 | 'ResNet101V2', 15 | 'ResNet152V2', 16 | 'ResNet50V2', 17 | 'VGG16', 18 | 'VGG19', 19 | 'Xception' 20 | ] 21 | 22 | export default transferLearningOptions 23 | -------------------------------------------------------------------------------- /labellab-client/src/components/navbar/css/searchbar.css: -------------------------------------------------------------------------------- 1 | .searchbar-parent { 2 | width: 340px; 3 | height: 46px; 4 | border-radius: 5px; 5 | } 6 | 7 | @media only screen and (min-width: 600px) { 8 | .searchbar-parent { 9 | position: absolute; 10 | margin-left: 184px; 11 | } 12 | } 13 | 14 | .size { 15 | /* font-size: 1.1em !important; */ 16 | } 17 | -------------------------------------------------------------------------------- /labellab-client/src/components/project/css/analytics.css: -------------------------------------------------------------------------------- 1 | .project-analytics-parent { 2 | margin: 0 2rem 2rem 0; 3 | display: flex; 4 | flex-direction: column; 5 | } 6 | 7 | .analytics-row { 8 | display: flex; 9 | flex-direction: row; 10 | justify-content: space-evenly; 11 | } 12 | 13 | .project-analytics-section { 14 | width: 100%; 15 | padding: 1em; 16 | box-shadow: 0px 0px 5px #ccc; 17 | border: 1px solid #ccc; 18 | border-radius: 20px; 19 | } 20 | 21 | .analytics-column { 22 | padding-left: 0px !important; 23 | } -------------------------------------------------------------------------------- /labellab-client/src/components/project/css/images.css: -------------------------------------------------------------------------------- 1 | .image-parent { 2 | padding: 1em; 3 | display: flex; 4 | flex-direction: row; 5 | flex-wrap: wrap; 6 | } 7 | .image-parent img { 8 | padding: 0 1em !important; 9 | } 10 | .image-file-input { 11 | width: 0.1px; 12 | height: 0.1px; 13 | opacity: 0; 14 | overflow: hidden; 15 | position: absolute; 16 | z-index: -1; 17 | margin: 10px; 18 | } 19 | .flex { 20 | display: flex; 21 | } 22 | .image-table-body { 23 | flex: 1; 24 | overflow-y: auto; 25 | overflow-x: hidden; 26 | } 27 | .max-size-error { 28 | color: red; 29 | } 30 | .custom-margin { 31 | margin-bottom: 1rem !important; 32 | } 33 | .image-table-container { 34 | width: 100%; 35 | padding-right: 20px; 36 | } 37 | .image-table { 38 | display: flex; 39 | flex-direction: column; 40 | height: 30em; 41 | margin-right: 200px; 42 | background-color: red; 43 | } 44 | 45 | .max-size-error { 46 | color: red; 47 | } 48 | .custom-margin { 49 | margin-bottom: 1rem !important; 50 | } 51 | .image-table-container { 52 | width: 100%; 53 | padding-right: 20px; 54 | } 55 | -------------------------------------------------------------------------------- /labellab-client/src/components/project/css/index.css: -------------------------------------------------------------------------------- 1 | .project-main { 2 | display: flex; 3 | flex-direction: row; 4 | } 5 | 6 | .project-non-side-section { 7 | width: 100%; 8 | margin-right: unset !important; 9 | margin-top: 4em; 10 | } 11 | 12 | .margin-v { 13 | margin: 10px 0px !important; 14 | } 15 | 16 | @media only screen and (max-width: 767px) { 17 | .project-main { 18 | margin: 0 !important; 19 | flex-direction: column; 20 | } 21 | 22 | .project-non-side-section { 23 | padding: 10px; 24 | max-width: unset !important; 25 | width: 100% !important; 26 | margin-right: auto; 27 | min-height: 50%; 28 | } 29 | } 30 | 31 | .labelDropdown { 32 | margin-left: 25vw; 33 | } 34 | -------------------------------------------------------------------------------- /labellab-client/src/components/project/css/issues.css: -------------------------------------------------------------------------------- 1 | .issue-status-label { 2 | width: 100% 3 | } 4 | .center { 5 | text-align: center !important; 6 | } 7 | .left { 8 | text-align: left !important; 9 | } 10 | .user-icon { 11 | font-size: 2.4em !important; 12 | color: grey; 13 | margin-top: 0.5rem !important; 14 | } 15 | .issue-header { 16 | text-align: left !important; 17 | cursor: pointer; 18 | } 19 | .issue-item { 20 | text-align: center !important; 21 | } 22 | .issue-activity { 23 | color: black !important; 24 | } 25 | .comment-section { 26 | height: 30vh; 27 | overflow-y: scroll; 28 | display: flex; 29 | flex-direction: column-reverse; 30 | } 31 | .activity-section { 32 | height: 30vh; 33 | overflow-y: scroll; 34 | } 35 | .detail-header { 36 | margin-bottom: 0.5em !important; 37 | } 38 | .ui.header:last-child { 39 | margin-top: 0; 40 | } -------------------------------------------------------------------------------- /labellab-client/src/components/project/css/labelItem.css: -------------------------------------------------------------------------------- 1 | .modal-actions { 2 | display: flex; 3 | flex-direction: column; 4 | align-items: center; 5 | } 6 | 7 | .modal-actions > div { 8 | padding-bottom: 1.5em; 9 | padding-top: 1.5em; 10 | } 11 | 12 | .label-container { 13 | overflow: auto 14 | } -------------------------------------------------------------------------------- /labellab-client/src/components/project/css/models.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scorelab/LabelLab/080a7cc7fa5a32b042535b1e1214b60bf5881501/labellab-client/src/components/project/css/models.css -------------------------------------------------------------------------------- /labellab-client/src/components/project/css/searchUser.css: -------------------------------------------------------------------------------- 1 | .searchbar-user-parent{ 2 | float: left; 3 | margin-bottom: 1em; 4 | } -------------------------------------------------------------------------------- /labellab-client/src/components/project/css/sidebar.css: -------------------------------------------------------------------------------- 1 | .sidebar-container { 2 | display: flex; 3 | align-items: center; 4 | flex-direction: column; 5 | } 6 | 7 | .sidebar-parent { 8 | width: 25%; 9 | display: flex; 10 | align-items: center; 11 | flex-direction: column; 12 | justify-content: space-between; 13 | } 14 | .profile-first-leftbar { 15 | margin: 1em; 16 | } 17 | .sidebar-image-button { 18 | display: flex; 19 | flex-direction: row; 20 | justify-content: center; 21 | } 22 | .sidebar-menu-parent { 23 | margin-top: 2em; 24 | margin-bottom: 2em; 25 | display: flex; 26 | flex-direction: row; 27 | justify-content: center; 28 | } 29 | .delete-project-button { 30 | margin-top: 2rem !important; 31 | width: 100%; 32 | } 33 | 34 | @media only screen and (max-width: 767px) { 35 | .delete-project-button { 36 | margin: 2rem 0 0 0 !important; 37 | width: 100%; 38 | } 39 | 40 | .sidebar-parent { 41 | width: 100%; 42 | margin: 0 !important; 43 | display: flex; 44 | align-items: center; 45 | flex-direction: column; 46 | justify-content: space-between; 47 | } 48 | 49 | .sidebar-menu-parent { 50 | width: 100%; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /labellab-client/src/components/project/css/team.css: -------------------------------------------------------------------------------- 1 | .add-member-button { 2 | padding: 2em 0; 3 | } 4 | .add-member { 5 | color: white !important; 6 | } 7 | .team-remove-user-icon:hover { 8 | cursor: pointer; 9 | } 10 | 11 | .ui.container { 12 | margin-left: unset !important; 13 | } 14 | 15 | .all-teams { 16 | margin-right: 20px !important; 17 | } 18 | 19 | .my-team { 20 | margin: 0 !important; 21 | } 22 | 23 | .team-management-conatiner { 24 | display: flex !important; 25 | flex-direction: row !important; 26 | } 27 | 28 | @media only screen and (max-width: 767px) { 29 | .ui.container { 30 | width: 100% !important; 31 | } 32 | } 33 | 34 | .team-item { 35 | cursor: pointer; 36 | } 37 | -------------------------------------------------------------------------------- /labellab-client/src/components/redirect.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import { Header } from 'semantic-ui-react' 3 | class Redirect extends Component { 4 | // componentDidMount() { 5 | // let token = window.location.search.substring(1) 6 | // if (token) { 7 | // setToken(TOKEN_TYPE, token, true) 8 | // } 9 | // } 10 | render() { 11 | return ( 12 | 13 |
14 | 15 | ) 16 | } 17 | } 18 | 19 | export default Redirect 20 | -------------------------------------------------------------------------------- /labellab-client/src/components/register/css/register.css: -------------------------------------------------------------------------------- 1 | @media only screen and (max-width: 600px) { 2 | .register-parent { 3 | width: 80% !important; 4 | } 5 | .register-submit { 6 | width: 100% !important; 7 | } 8 | } 9 | 10 | .register-parent { 11 | display: flex; 12 | flex-direction: column; 13 | height: 100%; 14 | padding: 5em 0px; 15 | width: 30%; 16 | margin-left: auto; 17 | margin-right: auto; 18 | box-sizing: border-box; 19 | } 20 | 21 | .errorText { 22 | color: #9f3a38; 23 | padding: 0px 10px 10px 10px; 24 | } 25 | 26 | .register-form { 27 | margin-top: 1.2em; 28 | } 29 | 30 | .register-login { 31 | padding: 1em 0; 32 | } 33 | -------------------------------------------------------------------------------- /labellab-client/src/constants/analytics.js: -------------------------------------------------------------------------------- 1 | export const ANALYTICS_TIME_LABEL_FAILURE = 'ANALYTICS_TIME_LABEL_FAILURE', 2 | ANALYTICS_TIME_LABEL_REQUEST = 'ANALYTICS_TIME_LABEL_REQUEST', 3 | ANALYTICS_TIME_LABEL_SUCCESS = 'ANALYTICS_TIME_LABEL_SUCCESS', 4 | ANALYTICS_COUNT_LABEL_FAILURE = 'ANALYTICS_COUNT_LABEL_FAILURE', 5 | ANALYTICS_COUNT_LABEL_REQUEST = 'ANALYTICS_COUNT_LABEL_REQUEST', 6 | ANALYTICS_COUNT_LABEL_SUCCESS = 'ANALYTICS_COUNT_LABEL_SUCCESS', 7 | ISSUE_ANALYTICS_FAILURE = 'ISSUE_ANALYTICS_FAILURE', 8 | ISSUE_ANALYTICS_REQUEST = 'ISSUE_ANALYTICS_REQUEST', 9 | ISSUE_ANALYTICS_SUCCESS = 'ISSUE_ANALYTICS_SUCCESS' 10 | 11 | -------------------------------------------------------------------------------- /labellab-client/src/constants/auth.js: -------------------------------------------------------------------------------- 1 | export const LOGIN_REQUEST = 'LOGIN_REQUEST', 2 | LOGIN_SUCCESS = 'LOGIN_SUCCESS', 3 | LOGIN_FAILURE = 'LOGIN_FAILURE', 4 | SET_USER_AUTH = 'SET_USER_AUTH', 5 | LOGOUT_REQUEST = 'LOGOUT_REQUEST', 6 | LOGOUT_SUCCESS = 'LOGOUT_SUCCESS', 7 | SEND_EMAIL_REQUEST = 'SEND_EMAIL_REQUEST', 8 | SENT_EMAIL_SUCCESS = 'SENT_EMAIL_SUCCESS', 9 | EMAIL_SENT_FAILURE = 'EMAIL_SENT_FAILURE', 10 | VERIFY_TOKEN_REQUEST = 'VERIFY_TOKEN_REQUEST', 11 | VERIFY_TOKEN_SUCCESS = 'VERIFY_TOKEN_SUCCESS', 12 | VERIFY_TOKEN_FAILURE = 'VERIFY_TOKEN_FAILURE', 13 | UPDATE_PASSWORD_REQUEST = 'UPDATE_PASSWORD_REQUEST', 14 | UPDATE_PASSWORD_SUCCESS = 'UPDATE_PASSWORD_SUCCESS', 15 | UPDATE_PASSWORD_FAILURE = 'UPDATE_PASSWORD_FAILURE', 16 | OAUTH_LOGIN_REQUEST = 'OAUTH_LOGIN_REQUEST', 17 | OAUTH_LOGIN_SUCCESS = 'OAUTH_LOGIN_SUCCESS', 18 | OAUTH_LOGIN_FAILURE = 'OAUTH_LOGIN_FAILURE', 19 | GITHUB_OAUTH_REQUEST = 'GITHUB_OAUTH_REQUEST', 20 | GITHUB_OAUTH_SUCCESS = 'GITHUB_OAUTH_SUCCESS', 21 | GITHUB_OAUTH_FAILURE = 'GITHUB_OAUTH_FAILURE', 22 | GITHUB_OAUTH_CALLBACK_REQUEST = 'GITHUB_OAUTH_CALLBACK_REQUEST', 23 | GITHUB_OAUTH_CALLBACK_SUCCESS = 'GITHUB_OAUTH_CALLBACK_SUCCESS', 24 | GITHUB_OAUTH_CALLBACK_FAILURE = 'GITHUB_OAUTH_CALLBACK_FAILURE' 25 | 26 | -------------------------------------------------------------------------------- /labellab-client/src/constants/image.js: -------------------------------------------------------------------------------- 1 | export const POST_IMAGE_REQUEST = 'POST_IMAGE_REQUEST', 2 | POST_IMAGE_SUCCESS = 'POST_IMAGE_SUCCESS', 3 | POST_IMAGE_FAILURE = 'POST_IMAGE_FAILURE', 4 | FETCH_IMAGE_FAILURE = 'FETCH_IMAGE_FAILURE', 5 | FETCH_IMAGE_REQUEST = 'FETCH_IMAGE_REQUEST', 6 | FETCH_IMAGE_SUCCESS = 'FETCH_IMAGE_SUCCESS', 7 | DELETE_IMAGE_REQUEST = 'DELETE_IMAGE_REQUEST', 8 | DELETE_IMAGE_FAILURE = 'DELETE_IMAGE_FAILURE', 9 | DELETE_IMAGE_SUCCESS = 'DELETE_IMAGE_SUCCESS', 10 | SET_IMAGE_STATE = 'SET_IMAGE_STATE' 11 | -------------------------------------------------------------------------------- /labellab-client/src/constants/index.js: -------------------------------------------------------------------------------- 1 | export * from './auth' 2 | export * from './register' 3 | export * from './user' 4 | export * from './project/index' 5 | export * from './image' 6 | export * from './issue' 7 | export * from './label' 8 | export * from './analytics' 9 | export * from './model' 10 | export * from './notification' 11 | export const TOKEN_TYPE = 'access_token' 12 | -------------------------------------------------------------------------------- /labellab-client/src/constants/label.js: -------------------------------------------------------------------------------- 1 | export const CREATE_LABEL_REQUEST = 'CREATE_LABEL_REQUEST', 2 | CREATE_LABEL_SUCCESS = 'CREATE_LABEL_SUCCESS', 3 | CREATE_LABEL_FAILURE = 'CREATE_LABEL_FAILURE', 4 | UPDATE_LABEL_FAILURE = 'UPDATE_LABEL_FAILURE', 5 | UPDATE_LABEL_REQUEST = 'UPDATE_LABEL_REQUEST', 6 | UPDATE_LABEL_SUCCESS = 'UPDATE_LABEL_SUCCESS', 7 | DELETE_LABEL_FAILURE = 'DELETE_LABEL_FAILURE', 8 | DELETE_LABEL_REQUEST = 'DELETE_LABEL_REQUEST', 9 | DELETE_LABEL_SUCCESS = 'DELETE_LABEL_SUCCESS', 10 | UPDATE_A_LABEL_FAILURE = 'UPDATE_A_LABEL_FAILURE', 11 | UPDATE_A_LABEL_REQUEST = 'UPDATE_A_LABEL_REQUEST', 12 | UPDATE_A_LABEL_SUCCESS = 'UPDATE_A_LABEL_SUCCESS' 13 | 14 | -------------------------------------------------------------------------------- /labellab-client/src/constants/notification.js: -------------------------------------------------------------------------------- 1 | export const FETCH_NOTIFICATION_REQUEST = 'FETCH_NOTIFICATION_REQUEST', 2 | FETCH_NOTIFICATION_SUCCESS = 'FETCH_NOTIFICATION_SUCCESS', 3 | FETCH_NOTIFICATION_FAILURE = 'FETCH_NOTIFICATION_FAILURE', 4 | REMOVE_TOAST_NOTIFICATION = 'REMOVE_TOAST_NOTIFICATION', 5 | RECEIVE_NOTIFICATION = 'RECEIVE_NOTIFICATION' 6 | -------------------------------------------------------------------------------- /labellab-client/src/constants/project/fetchDetails.js: -------------------------------------------------------------------------------- 1 | export const FETCH_PROJECT_REQUEST = 'FETCH_PROJECT_REQUEST', 2 | FETCH_PROJECT_SUCCESS = 'FETCH_PROJECT_SUCCESS', 3 | FETCH_PROJECT_FAILURE = 'FETCH_PROJECT_FAILURE', 4 | FETCH_PROJECT_ALL_FAILURE = 'FETCH_PROJECT_ALL_FAILURE', 5 | FETCH_PROJECT_ALL_REQUEST = 'FETCH_PROJECT_ALL_REQUEST', 6 | FETCH_PROJECT_ALL_SUCCESS = 'FETCH_PROJECT_ALL_SUCCESS', 7 | FETCH_LABEL_SUCCESS = 'FETCH_LABEL_SUCCESS', 8 | FETCH_LABEL_REQUEST = 'FETCH_LABEL_REQUEST', 9 | FETCH_LABEL_FAILURE = 'FETCH_LABEL_FAILURE', 10 | FETCH_PROJECT_ROLES_REQUEST = 'FETCH_PROJECT_ROLES_REQUEST', 11 | FETCH_PROJECT_ROLES_SUCCESS = 'FETCH_PROJECT_ROLES_SUCCESS', 12 | FETCH_PROJECT_ROLES_FAILURE = 'FETCH_PROJECT_ROLES_FAILURE' 13 | -------------------------------------------------------------------------------- /labellab-client/src/constants/project/index.js: -------------------------------------------------------------------------------- 1 | export * from './member' 2 | export * from './fetchDetails' 3 | export * from './search' 4 | export * from './projectDetails' 5 | export * from './teams' 6 | export * from './pathTracking' 7 | export * from './logs' 8 | export const DELETE_PROJECT_REQUEST = 'DELETE_PROJECT_REQUEST', 9 | DELETE_PROJECT_FAILURE = 'DELETE_PROJECT_FAILURE', 10 | DELETE_PROJECT_SUCCESS = 'DELETE_PROJECT_SUCCESS', 11 | LEAVE_PROJECT_REQUEST = 'LEAVE_PROJECT_REQUEST', 12 | LEAVE_PROJECT_SUCCESS = 'LEAVE_PROJECT_SUCCESS', 13 | LEAVE_PROJECT_FAILURE = 'LEAVE_PROJECT_FAILURE' 14 | -------------------------------------------------------------------------------- /labellab-client/src/constants/project/logs.js: -------------------------------------------------------------------------------- 1 | export const FETCH_PROJECT_LOGS_REQUEST = 'FETCH_PROJECT_LOGS_REQUEST', 2 | FETCH_PROJECT_LOGS_SUCCESS = 'FETCH_PROJECT_LOGS_SUCCESS', 3 | FETCH_PROJECT_LOGS_FAILURE = 'FETCH_PROJECT_LOGS_FAILURE', 4 | FETCH_CATEGORY_SPECIFIC_LOGS_REQUEST = 'FETCH_CATEGORY_SPECIFIC_LOGS_REQUEST', 5 | FETCH_CATEGORY_SPECIFIC_LOGS_SUCCESS = 'FETCH_CATEGORY_SPECIFIC_LOGS_SUCCESS', 6 | FETCH_CATEGORY_SPECIFIC_LOGS_FAILURE = 'FETCH_CATEGORY_SPECIFIC_LOGS_FAILURE', 7 | FETCH_MEMBER_SPECIFIC_LOGS_REQUEST = 'FETCH_MEMBER_SPECIFIC_LOGS_REQUEST', 8 | FETCH_MEMBER_SPECIFIC_LOGS_SUCCESS = 'FETCH_MEMBER_SPECIFIC_LOGS_SUCCESS', 9 | FETCH_MEMBER_SPECIFIC_LOGS_FAILURE = 'FETCH_MEMBER_SPECIFIC_LOGS_FAILURE', 10 | FETCH_ENTITY_SPECIFIC_LOGS_REQUEST = 'FETCH_ENTITY_SPECIFIC_LOGS_REQUEST', 11 | FETCH_ENTITY_SPECIFIC_LOGS_SUCCESS = 'FETCH_ENTITY_SPECIFIC_LOGS_SUCCESS', 12 | FETCH_ENTITY_SPECIFIC_LOGS_FAILURE = 'FETCH_ENTITY_SPECIFIC_LOGS_FAILURE' 13 | -------------------------------------------------------------------------------- /labellab-client/src/constants/project/member.js: -------------------------------------------------------------------------------- 1 | export const DELETE_MEMBER_FAILURE = 'DELETE_MEMBER_FAILURE', 2 | DELETE_MEMBER_REQUEST = 'DELETE_MEMBER_REQUEST', 3 | DELETE_MEMBER_SUCCESS = 'DELETE_MEMBER_SUCCESS', 4 | ADD_MEMBER_REQUEST = 'ADD_MEMBER_REQUEST', 5 | ADD_MEMBER_SUCCESS = 'ADD_MEMBER_SUCCESS', 6 | ADD_MEMBER_FAILURE = 'ADD_MEMBER_FAILURE' 7 | -------------------------------------------------------------------------------- /labellab-client/src/constants/project/pathTracking.js: -------------------------------------------------------------------------------- 1 | export const FETCH_COORDINATES_FAILURE = 'FETCH_COORDINATES_FAILURE', 2 | FETCH_COORDINATES_REQUEST = 'FETCH_COORDINATES_REQUEST', 3 | FETCH_COORDINATES_SUCCESS = 'FETCH_COORDINATES_SUCCESS' -------------------------------------------------------------------------------- /labellab-client/src/constants/project/projectDetails.js: -------------------------------------------------------------------------------- 1 | export const INITIALIZE_PROJECT_REQUEST = 'INITIALIZE_PROJECT_REQUEST', 2 | INITIALIZE_PROJECT_SUCCESS = 'INITIALIZE_PROJECT_SUCCESS', 3 | INITIALIZE_PROJECT_FAILURE = 'INITIALIZE_PROJECT_FAILURE', 4 | UPDATE_PROJECT_REQUEST = 'UPDATE_PROJECT_REQUEST', 5 | UPDATE_PROJECT_SUCCESS = 'UPDATE_PROJECT_SUCCESS', 6 | UPDATE_PROJECT_FAILURE = 'UPDATE_PROJECT_FAILURE' 7 | -------------------------------------------------------------------------------- /labellab-client/src/constants/project/search.js: -------------------------------------------------------------------------------- 1 | export const SEARCH_PROJECTS = 'SEARCH_PROJECTS', 2 | SEARCH_PROJECTS_FAILURE = 'SEARCH_PROJECTS_FAILURE' 3 | -------------------------------------------------------------------------------- /labellab-client/src/constants/project/teams.js: -------------------------------------------------------------------------------- 1 | export const FETCH_TEAMS_FAILURE = 'FETCH_TEAMS_FAILURE', 2 | FETCH_TEAMS_REQUEST = 'FETCH_TEAMS_REQUEST', 3 | FETCH_TEAMS_SUCCESS = 'FETCH_TEAMS_SUCCESS', 4 | DELETE_TEAM_FAILURE = 'DELETE_TEAM_FAILURE', 5 | DELETE_TEAM_REQUEST = 'DELETE_TEAM_REQUEST', 6 | DELETE_TEAM_SUCCESS = 'DELETE_TEAM_SUCCESS', 7 | FETCH_TEAM_REQUEST = 'FETCH_TEAM_REQUEST', 8 | FETCH_TEAM_SUCCESS = 'FETCH_TEAM_SUCCESS', 9 | FETCH_TEAM_FAILURE = 'FETCH_TEAM_FAILURE', 10 | UPDATE_TEAM_REQUEST = 'UPDATE_TEAM_REQUEST', 11 | UPDATE_TEAM_SUCCESS = 'UPDATE_TEAM_SUCCESS', 12 | UPDATE_TEAM_FAILURE = 'UPDATE_TEAM_FAILURE', 13 | ADD_TEAM_MEMBER_REQUEST = 'ADD_TEAM_MEMBER_REQUEST', 14 | ADD_TEAM_MEMBER_SUCCESS = 'ADD_TEAM_MEMBER_SUCCESS', 15 | ADD_TEAM_MEMBER_FAILURE = 'ADD_TEAM_MEMBER_FAILURE', 16 | REMOVE_TEAM_MEMBER_REQUEST = 'REMOVE_TEAM_MEMBER_REQUEST', 17 | REMOVE_TEAM_MEMBER_SUCCESS = 'REMOVE_TEAM_MEMBER_SUCCESS', 18 | REMOVE_TEAM_MEMBER_FAILURE = 'REMOVE_TEAM_MEMBER_FAILURE', 19 | FETCH_TEAM_MESSAGES_REQUEST = 'FETCH_TEAM_MESSAGES_REQUEST', 20 | FETCH_TEAM_MESSAGES_SUCCESS = 'FETCH_TEAM_MESSAGES_SUCCESS', 21 | FETCH_TEAM_MESSAGES_FAILURE = 'FETCH_TEAM_MESSAGES_FAILURE', 22 | SEND_MESSAGE = 'SEND_MESSAGE', 23 | RECEIVE_MESSAGE = 'RECEIVE_MESSAGE' 24 | -------------------------------------------------------------------------------- /labellab-client/src/constants/register.js: -------------------------------------------------------------------------------- 1 | export const REGISTER_REQUEST = 'REGISTER_REQUEST', 2 | REGISTER_SUCCESS = 'REGISTER_SUCCESS', 3 | REGISTER_FAILURE = 'REGISTER_FAILURE' 4 | -------------------------------------------------------------------------------- /labellab-client/src/constants/user.js: -------------------------------------------------------------------------------- 1 | export const SET_USER_DATA_REQUEST = 'SET_USER_DATA_REQUEST', 2 | SET_USER_DATA_SUCCESS = 'SET_USER_DATA_SUCCESS', 3 | SET_USER_DATA_FAILURE = 'SET_USER_DATA_FAILURE', 4 | UPLOAD_USER_IMAGE_REQUEST = 'UPLOAD_USER_IMAGE_REQUEST', 5 | UPLOAD_USER_IMAGE_SUCCESS = 'UPLOAD_USER_IMAGE_SUCCESS', 6 | UPLOAD_USER_IMAGE_FAILURE = 'UPLOAD_USER_IMAGE_FAILURE', 7 | FETCH_COUNT_FAILURE = 'FETCH_COUNT_FAILURE', 8 | FETCH_COUNT_REQUEST = 'FETCH_COUNT_REQUEST', 9 | FETCH_COUNT_SUCCESS = 'FETCH_COUNT_SUCCESS', 10 | FETCH_ALL_USERS_REQUEST = 'FETCH_ALL_USERS_REQUEST', 11 | FETCH_ALL_USERS_SUCCESS = 'FETCH_ALL_USERS_SUCCESS', 12 | FETCH_ALL_USERS_FAILURE = 'FETCH_ALL_USERS_FAILURE', 13 | SEARCH_USER = 'SEARCH_USER', 14 | SEARCH_USER_FAILURE = 'SEARCH_USER_FAILURE', 15 | EDIT_USER_INFO = 'EDIT_USER_INFO', 16 | EDIT_USER_INFO_FAILURE = 'EDIT_USER_INFO_FAILURE' 17 | -------------------------------------------------------------------------------- /labellab-client/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | } 5 | body .canvas-container { 6 | position: fixed; 7 | bottom: 0; 8 | right: 0; 9 | z-index: -5000; 10 | opacity: 0; 11 | } -------------------------------------------------------------------------------- /labellab-client/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom' 3 | import { Provider } from 'react-redux' 4 | import { store } from './utils/store' 5 | import './index.css' 6 | import 'semantic-ui-css/semantic.min.css' 7 | import App from './App' 8 | import * as serviceWorker from './serviceWorker' 9 | ReactDOM.render( 10 | 11 | 12 | , 13 | document.getElementById('root') 14 | ) 15 | 16 | // If you want your app to work offline and load faster, you can change 17 | // unregister() to register() below. Note this comes with some pitfalls. 18 | // Learn more about service workers: https://bit.ly/CRA-PWA 19 | serviceWorker.unregister() 20 | -------------------------------------------------------------------------------- /labellab-client/src/reducers/index.js: -------------------------------------------------------------------------------- 1 | import { combineReducers } from 'redux' 2 | import auth from './auth' 3 | import register from './register' 4 | import user from './user' 5 | import project from './project' 6 | import image from './image' 7 | import issues from './issue' 8 | import label from './label' 9 | import searchProjects from './search' 10 | import searchUser from './searchUser' 11 | import analytics from './analytics' 12 | import model from './model' 13 | import teams from './teams' 14 | import logs from './logs' 15 | import notifications from './notification' 16 | 17 | const rootReducers = combineReducers({ 18 | auth, 19 | register, 20 | user, 21 | searchProjects, 22 | searchUser, 23 | analytics, 24 | model, 25 | projects: project, 26 | images: image, 27 | labels: label, 28 | teams, 29 | logs, 30 | issues, 31 | notifications 32 | }) 33 | 34 | export default rootReducers 35 | -------------------------------------------------------------------------------- /labellab-client/src/reducers/register.js: -------------------------------------------------------------------------------- 1 | import { 2 | REGISTER_FAILURE, 3 | REGISTER_REQUEST, 4 | REGISTER_SUCCESS 5 | } from '../constants/index' 6 | const intialState = { 7 | isRegistering: false, 8 | error: false, 9 | errField: '', 10 | statusText: '' 11 | } 12 | const register = (state = intialState, action) => { 13 | switch (action.type) { 14 | case REGISTER_REQUEST: 15 | return { 16 | ...state, 17 | isRegistering: true, 18 | error: false 19 | } 20 | case REGISTER_SUCCESS: 21 | return { 22 | ...state, 23 | isRegistering: false, 24 | statusText: action.payload, 25 | error: false 26 | } 27 | case REGISTER_FAILURE: 28 | return { 29 | ...state, 30 | isRegistering: false, 31 | statusText: action.payload, 32 | errField: action.other, 33 | error: true 34 | } 35 | default: 36 | return state 37 | } 38 | } 39 | 40 | export default register 41 | -------------------------------------------------------------------------------- /labellab-client/src/reducers/search.js: -------------------------------------------------------------------------------- 1 | import { SEARCH_PROJECTS, SEARCH_PROJECTS_FAILURE } from '../constants/index' 2 | const searchProjects = (state = [], action) => { 3 | switch (action.type) { 4 | case SEARCH_PROJECTS: 5 | return action.payload 6 | case SEARCH_PROJECTS_FAILURE: 7 | return action.payload 8 | default: 9 | return state 10 | } 11 | } 12 | export default searchProjects 13 | -------------------------------------------------------------------------------- /labellab-client/src/reducers/searchUser.js: -------------------------------------------------------------------------------- 1 | import { SEARCH_USER, SEARCH_USER_FAILURE } from '../constants/index' 2 | const searchUser = (state = [], action) => { 3 | switch (action.type) { 4 | case SEARCH_USER: 5 | return action.payload 6 | case SEARCH_USER_FAILURE: 7 | return action.payload 8 | default: 9 | return state 10 | } 11 | } 12 | export default searchUser 13 | -------------------------------------------------------------------------------- /labellab-client/src/utils/TestUtils.js: -------------------------------------------------------------------------------- 1 | import checkPropTypes from "check-prop-types"; 2 | import { applyMiddleware, createStore } from "redux"; 3 | import { middleware } from "./store"; 4 | import rootReducers from "../reducers"; 5 | 6 | export const findByTestAttr = (component, attr) => { 7 | const wrapper = component.find(`[className='${attr}']`); 8 | return wrapper; 9 | }; 10 | 11 | export const checkProps = (component, expectedProps) => { 12 | const propsErr = checkPropTypes( 13 | component.propTypes, 14 | expectedProps, 15 | "props", 16 | component.name 17 | ); 18 | return propsErr; 19 | }; 20 | 21 | export const testStore = initialState => { 22 | const createStoreWithMiddleware = applyMiddleware(...middleware)( 23 | createStore 24 | ); 25 | return createStoreWithMiddleware(rootReducers, initialState); 26 | }; -------------------------------------------------------------------------------- /labellab-client/src/utils/cardLoader/card-loader.css: -------------------------------------------------------------------------------- 1 | .card-loader-height { 2 | height: 125px; 3 | } 4 | -------------------------------------------------------------------------------- /labellab-client/src/utils/helpers.js: -------------------------------------------------------------------------------- 1 | export const isEmptyObject = obj => Object.keys(obj).length === 0 2 | 3 | export const isEmpty = obj => obj === '' || obj === null || obj === 0 4 | 5 | export const isLengthBetween = (obj, range) => 6 | obj.length >= range.min && obj.length <= range.max 7 | 8 | export const isEmail = email => 9 | /^[a-zA-Z0-9._%+-]+@[A-Za-z0-9.-]+\.[a-zA-Z]{2,4}$/.test(email) 10 | 11 | export const isMobilePhone = phone => /^(\+?91|0)?[789]\d{9}$/.test(phone) 12 | 13 | export const validateForm = ({ errors, ...rest }) => { 14 | let valid = true 15 | 16 | // validate errors being empty 17 | Object.values(errors).forEach(val => { 18 | val.length && (valid = false) 19 | }) 20 | 21 | // validate if form is empty 22 | Object.values(rest).forEach(val => { 23 | typeof val !== 'boolean' && !val.length && (valid = false) 24 | }) 25 | 26 | return valid 27 | } 28 | -------------------------------------------------------------------------------- /labellab-client/src/utils/pR.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { Route, Redirect } from 'react-router-dom' 3 | import { hasToken } from '../utils/token' 4 | import { TOKEN_TYPE } from '../constants/index' 5 | const PrivateRoute = ({ component: Component, ...rest }) => ( 6 | 9 | hasToken(TOKEN_TYPE) ? ( 10 | 11 | ) : ( 12 | 15 | ) 16 | } 17 | /> 18 | ) 19 | 20 | export default PrivateRoute 21 | -------------------------------------------------------------------------------- /labellab-client/src/utils/store.js: -------------------------------------------------------------------------------- 1 | import { createStore, compose, applyMiddleware } from 'redux' 2 | import thunk from 'redux-thunk' 3 | import rootReducer from '../reducers/index' 4 | 5 | const initialState = {} 6 | export const middleware = [thunk] 7 | const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose 8 | 9 | export const store = createStore( 10 | rootReducer, 11 | initialState, 12 | composeEnhancers(applyMiddleware(...middleware)) 13 | ) 14 | -------------------------------------------------------------------------------- /labellab-client/src/utils/webSocket.js: -------------------------------------------------------------------------------- 1 | import openSocket from 'socket.io-client' 2 | 3 | const URL = `http://${process.env.REACT_APP_HOST}:${process.env.REACT_APP_SERVER_PORT}` 4 | 5 | const socket = openSocket(URL, { transports: ['polling'] }) 6 | 7 | export default socket 8 | -------------------------------------------------------------------------------- /labellab-flask/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | npm-debug.log 3 | Dockerfile* 4 | docker-compose* 5 | .dockerignore 6 | .git 7 | .gitignore 8 | .env 9 | */bin 10 | */obj 11 | README.md 12 | LICENSE 13 | .vscode -------------------------------------------------------------------------------- /labellab-flask/.envsample: -------------------------------------------------------------------------------- 1 | export FLASK_APP="app.py" 2 | export FLASK_ENV="" 3 | export FLASK_CONFIG="" 4 | 5 | export DEV_DATABASE_URL= "mysql+pymysql://" + username + ":" + password + "@" + host + "/labellab" 6 | export TEST_DATABASE_URL="mysql+pymysql://" + username + ":" + password + "@" + host + "/test_labellab" 7 | export DATABASE_URL="" 8 | 9 | export API_KEY="" -------------------------------------------------------------------------------- /labellab-flask/.flake8: -------------------------------------------------------------------------------- 1 | [flake8] 2 | ignore = E203, E266, E501, W503, F403, F401 3 | max-line-length = 79 4 | max-complexity = 18 5 | select = B,C,E,F,W,T4,B9 -------------------------------------------------------------------------------- /labellab-flask/.gcloudignore: -------------------------------------------------------------------------------- 1 | # This file specifies files that are *not* uploaded to Google Cloud Platform 2 | # using gcloud. It follows the same syntax as .gitignore, with the addition of 3 | # "#!include" directives (which insert the entries of the given .gitignore-style 4 | # file at that point). 5 | # 6 | # For more information, run: 7 | # $ gcloud topic gcloudignore 8 | # 9 | .gcloudignore 10 | # If you would like to upload your .git directory, .gitignore file or files 11 | # from your .gitignore file, remove the corresponding line 12 | # below: 13 | .git 14 | .gitignore 15 | 16 | # Python pycache: 17 | __pycache__/ 18 | # Ignored by the build system 19 | /setup.cfg -------------------------------------------------------------------------------- /labellab-flask/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.7 2 | 3 | RUN pip3 install --upgrade pip 4 | 5 | ENV FLASK_APP app.py 6 | ENV FLASK_CONFIG docker 7 | 8 | RUN mkdir -p /usr/labellab/labellab-flask 9 | WORKDIR /usr/labellab/labellab-flask 10 | 11 | COPY requirements.txt requirements.txt 12 | COPY docker.txt docker.txt 13 | RUN pip install -r docker.txt 14 | COPY ./boot.sh /boot.sh 15 | 16 | RUN chmod +x /boot.sh 17 | 18 | EXPOSE 5000 19 | 20 | ENTRYPOINT [ "/boot.sh" ] -------------------------------------------------------------------------------- /labellab-flask/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scorelab/LabelLab/080a7cc7fa5a32b042535b1e1214b60bf5881501/labellab-flask/__init__.py -------------------------------------------------------------------------------- /labellab-flask/api/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scorelab/LabelLab/080a7cc7fa5a32b042535b1e1214b60bf5881501/labellab-flask/api/__init__.py -------------------------------------------------------------------------------- /labellab-flask/api/controllers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scorelab/LabelLab/080a7cc7fa5a32b042535b1e1214b60bf5881501/labellab-flask/api/controllers/__init__.py -------------------------------------------------------------------------------- /labellab-flask/api/helpers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scorelab/LabelLab/080a7cc7fa5a32b042535b1e1214b60bf5881501/labellab-flask/api/helpers/__init__.py -------------------------------------------------------------------------------- /labellab-flask/api/helpers/chatroom.py: -------------------------------------------------------------------------------- 1 | from sqlalchemy import desc 2 | 3 | from api.extensions import db 4 | from api.models.Message import Message 5 | 6 | # Get all messages of a team 7 | def get_all_messages(team_id): 8 | messages = Message.query.filter_by(team_id=team_id).order_by(desc('timestamp')).all() 9 | return list(map(lambda message: to_json(message), messages)) 10 | 11 | # Save message 12 | def save_message(message): 13 | db.session.add(message) 14 | db.session.commit() 15 | return to_json(message) 16 | 17 | def to_json(message): 18 | return { 19 | 'id': message.id, 20 | 'body': message.body, 21 | 'team_id': message.team_id, 22 | 'user_id': message.user_id, 23 | 'username': message.username, 24 | 'entity_type': message.entity_type, 25 | 'entity_id': message.entity_id, 26 | 'timestamp': str(message.timestamp), 27 | } -------------------------------------------------------------------------------- /labellab-flask/api/helpers/notification.py: -------------------------------------------------------------------------------- 1 | from sqlalchemy import desc 2 | 3 | from api.extensions import db 4 | from api.models.Notification import Notification 5 | from api.serializers.notification import NotificationSchema 6 | 7 | notification_schema = NotificationSchema() 8 | notifications_schema = NotificationSchema(many =True) 9 | 10 | # Fetch all notifications related to a user 11 | def fetch_all_user_notifications(user_id): 12 | notifications = Notification.query.filter_by(user_id=user_id).all() 13 | return list(map(lambda notification: to_json(notification), notifications)) 14 | 15 | # Save a notification to db 16 | def save_notification(notification): 17 | db.session.add(notification) 18 | db.session.commit() 19 | return notification_schema.dump(notification).data 20 | 21 | def to_json(notification): 22 | return { 23 | 'id': notification.id, 24 | 'message': notification.message, 25 | 'type': notification.type, 26 | 'user_id': notification.user_id 27 | } 28 | -------------------------------------------------------------------------------- /labellab-flask/api/middleware/comment_decorator.py: -------------------------------------------------------------------------------- 1 | from functools import wraps 2 | from flask import jsonify, make_response 3 | from flask_jwt_extended import get_jwt_identity 4 | 5 | from api.helpers.comment import find_by_id 6 | 7 | def comment_exists(fun): 8 | @wraps(fun) 9 | def wrap(*args, **kwargs): 10 | 11 | # Get comment id 12 | comment_id = kwargs.get('comment_id') 13 | comment = find_by_id(comment_id) 14 | 15 | if not comment: 16 | response = { 17 | 'success': False, 18 | 'msg': 'comment does not exist', 19 | } 20 | return make_response(jsonify(response)), 404 21 | 22 | return fun(*args, **kwargs) 23 | return wrap -------------------------------------------------------------------------------- /labellab-flask/api/middleware/image_access.py: -------------------------------------------------------------------------------- 1 | from functools import wraps 2 | from flask import jsonify, make_response 3 | from flask_jwt_extended import get_jwt_identity 4 | 5 | from api.helpers.project import find_by_project_id 6 | from api.helpers.user import get_user_roles 7 | 8 | def image_only(fun): 9 | @wraps(fun) 10 | def wrap(*args, **kwargs): 11 | 12 | # Get current user 13 | user_id = get_jwt_identity() 14 | 15 | # Get project and admin_id 16 | project_id = kwargs.get('project_id') 17 | project = find_by_project_id(project_id) 18 | 19 | if not project: 20 | response = { 21 | 'success': False, 22 | 'msg': 'Project does not exist', 23 | } 24 | return make_response(jsonify(response)), 404 25 | 26 | user_roles = get_user_roles(user_id, project_id) 27 | 28 | # If current user does not have images or admin role, then unauthorized 29 | if 'admin' not in user_roles and 'images' not in user_roles: 30 | response = { 31 | 'success': False, 32 | 'msg': 'Only a images team member can access this route', 33 | } 34 | return make_response(jsonify(response)), 401 35 | 36 | # Else continue 37 | return fun(*args, **kwargs) 38 | return wrap -------------------------------------------------------------------------------- /labellab-flask/api/middleware/image_labelling_access.py: -------------------------------------------------------------------------------- 1 | from functools import wraps 2 | from flask import jsonify, make_response 3 | from flask_jwt_extended import get_jwt_identity 4 | 5 | from api.helpers.project import find_by_project_id 6 | from api.helpers.user import get_user_roles 7 | 8 | def image_labelling_only(fun): 9 | @wraps(fun) 10 | def wrap(*args, **kwargs): 11 | 12 | # Get current user 13 | user_id = get_jwt_identity() 14 | 15 | # Get project and admin_id 16 | project_id = kwargs.get('project_id') 17 | project = find_by_project_id(project_id) 18 | 19 | if not project: 20 | response = { 21 | 'success': False, 22 | 'msg': 'Project does not exist', 23 | } 24 | return make_response(jsonify(response)), 404 25 | 26 | user_roles = get_user_roles(user_id, project_id) 27 | 28 | # If current user does not have image labelling or admin role, then unauthorized 29 | if 'admin' not in user_roles and 'image labelling' not in user_roles: 30 | response = { 31 | 'success': False, 32 | 'msg': 'Only a image labelling team member can access this route', 33 | } 34 | return make_response(jsonify(response)), 401 35 | 36 | # Else continue 37 | return fun(*args, **kwargs) 38 | return wrap -------------------------------------------------------------------------------- /labellab-flask/api/middleware/issue_decorator.py: -------------------------------------------------------------------------------- 1 | from functools import wraps 2 | from flask import jsonify, make_response 3 | from flask_jwt_extended import get_jwt_identity 4 | 5 | from api.helpers.issue import find_by_id 6 | 7 | def issue_exists(fun): 8 | @wraps(fun) 9 | def wrap(*args, **kwargs): 10 | 11 | # Get issue id 12 | issue_id = kwargs.get('issue_id') 13 | issue = find_by_id(issue_id) 14 | 15 | if not issue: 16 | response = { 17 | 'success': False, 18 | 'msg': 'Issue does not exist', 19 | } 20 | return make_response(jsonify(response)), 404 21 | 22 | return fun(*args, **kwargs) 23 | return wrap -------------------------------------------------------------------------------- /labellab-flask/api/middleware/label_access.py: -------------------------------------------------------------------------------- 1 | from functools import wraps 2 | from flask import jsonify, make_response 3 | from flask_jwt_extended import get_jwt_identity 4 | 5 | from api.helpers.project import find_by_project_id 6 | from api.helpers.user import get_user_roles 7 | 8 | def label_only(fun): 9 | @wraps(fun) 10 | def wrap(*args, **kwargs): 11 | 12 | # Get current user 13 | user_id = get_jwt_identity() 14 | 15 | # Get project and admin_id 16 | project_id = kwargs.get('project_id') 17 | project = find_by_project_id(project_id) 18 | 19 | if not project: 20 | response = { 21 | 'success': False, 22 | 'msg': 'Project does not exist', 23 | } 24 | return make_response(jsonify(response)), 404 25 | 26 | user_roles = get_user_roles(user_id, project_id) 27 | 28 | # If current user does not have labels or admin role, then unauthorized 29 | if 'admin' not in user_roles and 'labels' not in user_roles: 30 | response = { 31 | 'success': False, 32 | 'msg': 'Only a labels team member can access this route', 33 | } 34 | return make_response(jsonify(response)), 401 35 | 36 | # Else continue 37 | return fun(*args, **kwargs) 38 | return wrap -------------------------------------------------------------------------------- /labellab-flask/api/middleware/model_access.py: -------------------------------------------------------------------------------- 1 | from functools import wraps 2 | from flask import jsonify, make_response 3 | from flask_jwt_extended import get_jwt_identity 4 | 5 | from api.helpers.project import find_by_project_id 6 | from api.helpers.user import get_user_roles 7 | 8 | def model_only(fun): 9 | @wraps(fun) 10 | def wrap(*args, **kwargs): 11 | 12 | # Get current user 13 | user_id = get_jwt_identity() 14 | 15 | # Get project and admin_id 16 | project_id = kwargs.get('project_id') 17 | project = find_by_project_id(project_id) 18 | 19 | if not project: 20 | response = { 21 | 'success': False, 22 | 'msg': 'Project does not exist', 23 | } 24 | return make_response(jsonify(response)), 404 25 | 26 | user_roles = get_user_roles(user_id, project_id) 27 | 28 | # If current user does not have models or admin role, then unauthorized 29 | if 'admin' not in user_roles and 'models' not in user_roles: 30 | response = { 31 | 'success': False, 32 | 'msg': 'Only a models team member can access this route', 33 | } 34 | return make_response(jsonify(response)), 401 35 | 36 | # Else continue 37 | return fun(*args, **kwargs) 38 | return wrap -------------------------------------------------------------------------------- /labellab-flask/api/middleware/project_admin_access.py: -------------------------------------------------------------------------------- 1 | from functools import wraps 2 | from flask import jsonify, make_response 3 | from flask_jwt_extended import get_jwt_identity 4 | 5 | from api.helpers.project import find_by_project_id 6 | from api.helpers.user import get_user_roles 7 | 8 | def admin_only(fun): 9 | @wraps(fun) 10 | def wrap(*args, **kwargs): 11 | 12 | # Get current user 13 | user_id = get_jwt_identity() 14 | 15 | # Get project and admin_id 16 | project_id = kwargs.get('project_id') 17 | project = find_by_project_id(project_id) 18 | 19 | if not project: 20 | response = { 21 | 'success': False, 22 | 'msg': 'Project does not exist', 23 | } 24 | return make_response(jsonify(response)), 404 25 | 26 | user_roles = get_user_roles(user_id, project_id) 27 | 28 | # If current user does not have admin role, then unauthorized 29 | if 'admin' not in user_roles: 30 | response = { 31 | 'success': False, 32 | 'msg': 'Only an admin can access this route', 33 | } 34 | return make_response(jsonify(response)), 401 35 | 36 | # Else continue 37 | return fun(*args, **kwargs) 38 | return wrap -------------------------------------------------------------------------------- /labellab-flask/api/middleware/project_member_access.py: -------------------------------------------------------------------------------- 1 | from functools import wraps 2 | from flask import jsonify, make_response 3 | from flask_jwt_extended import get_jwt_identity 4 | 5 | from api.helpers.project import find_by_project_id 6 | from api.helpers.user import get_user_roles 7 | 8 | def project_member_only(fun): 9 | @wraps(fun) 10 | def wrap(*args, **kwargs): 11 | 12 | # Get current user 13 | user_id = get_jwt_identity() 14 | 15 | # Get project and admin_id 16 | project_id = kwargs.get('project_id') 17 | project = find_by_project_id(project_id) 18 | 19 | if not project: 20 | response = { 21 | 'success': False, 22 | 'msg': 'Project does not exist', 23 | } 24 | return make_response(jsonify(response)), 404 25 | 26 | user_roles = get_user_roles(user_id, project_id) 27 | 28 | # If current user has no roles in the project, then unauthorized 29 | if len(user_roles) == 0: 30 | response = { 31 | 'success': False, 32 | 'msg': 'Only a project member can access this route', 33 | } 34 | return make_response(jsonify(response)), 401 35 | 36 | # Else continue 37 | return fun(*args, **kwargs) 38 | return wrap -------------------------------------------------------------------------------- /labellab-flask/api/middleware/project_owner_access.py: -------------------------------------------------------------------------------- 1 | from functools import wraps 2 | from flask import jsonify, make_response 3 | from flask_jwt_extended import get_jwt_identity 4 | 5 | from api.helpers.project import find_by_project_id 6 | 7 | def project_owner_only(fun): 8 | @wraps(fun) 9 | def wrap(*args, **kwargs): 10 | 11 | # Get current user 12 | user_id = get_jwt_identity() 13 | 14 | # Get project and admin_id 15 | project_id = kwargs.get('project_id') 16 | project = find_by_project_id(project_id) 17 | 18 | if not project: 19 | response = { 20 | 'success': False, 21 | 'msg': 'Project does not exist', 22 | } 23 | return make_response(jsonify(response)), 404 24 | 25 | admin_id = project['admin_id'] 26 | 27 | # If current user is not equal to project admin, then unauthorized 28 | if user_id != admin_id: 29 | response = { 30 | 'success': False, 31 | 'msg': 'Only project owner can access this route', 32 | } 33 | return make_response(jsonify(response)), 401 34 | 35 | # Else continue 36 | return fun(*args, **kwargs) 37 | return wrap -------------------------------------------------------------------------------- /labellab-flask/api/models/Classification.py: -------------------------------------------------------------------------------- 1 | from flask import current_app 2 | from datetime import datetime 3 | 4 | from api.extensions import db, Base 5 | 6 | 7 | class Classification(db.Model): 8 | # This model holds information about classification requests by a user 9 | 10 | __tablename__ = "classification" 11 | 12 | id = db.Column(db.Integer, primary_key=True) 13 | image_name = db.Column(db.String(255), nullable=False,) 14 | image_url = db.Column(db.String(255), nullable=False,) 15 | label = db.Column(db.String(255)) 16 | confidence = db.Column(db.Float) 17 | user_id = db.Column(db.Integer, 18 | db.ForeignKey( 19 | 'user.id', ondelete="cascade", onupdate="cascade"), 20 | nullable=False) 21 | classified_at = db.Column(db.DateTime, default=datetime.now()) 22 | 23 | def __init__(self, image_name, image_url, label, confidence, user_id): 24 | self.image_name = image_name 25 | self.image_url = image_url 26 | self.label = label 27 | self.confidence = confidence 28 | self.user_id = user_id 29 | 30 | def __repr__(self): 31 | """ 32 | Returns the object reprensentation 33 | """ 34 | return "" % self.image_name 35 | -------------------------------------------------------------------------------- /labellab-flask/api/models/Log.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | 3 | from api.extensions import db 4 | 5 | class Log(db.Model): 6 | id = db.Column(db.Integer, primary_key=True) 7 | message = db.Column(db.String(120), nullable=False) 8 | category = db.Column(db.String(20), nullable=False) 9 | entity_type = db.Column(db.String(10)) 10 | entity_id = db.Column(db.Integer) 11 | user_id = db.Column(db.Integer, nullable=False) 12 | username = db.Column(db.String(20), nullable=False) 13 | project_id = db.Column(db.Integer, nullable=False) 14 | timestamp = db.Column(db.DateTime, nullable=False, default=datetime.utcnow) 15 | 16 | def __init__(self, message, category, entity_type, entity_id, user_id, project_id, username): 17 | self.message = message 18 | self.category = category 19 | self.entity_type = entity_type 20 | self.entity_id = entity_id 21 | self.user_id = user_id 22 | self.project_id = project_id 23 | self.username = username -------------------------------------------------------------------------------- /labellab-flask/api/models/Message.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | 3 | from api.extensions import db 4 | 5 | class Message(db.Model): 6 | id = db.Column(db.Integer, primary_key=True) 7 | body = db.Column(db.String(200), nullable=False) 8 | team_id = db.Column(db.Integer, nullable=False) 9 | user_id = db.Column(db.Integer, nullable=False) 10 | username = db.Column(db.String(20), nullable=False) 11 | entity_type = db.Column(db.String(10)) 12 | entity_id = db.Column(db.Integer) 13 | timestamp = db.Column(db.DateTime, nullable=False, default=datetime.utcnow) 14 | 15 | def __init__(self, body, team_id, user_id, username, entity_type=None, entity_id=None): 16 | self.body = body 17 | self.team_id = team_id 18 | self.user_id = user_id 19 | self.username = username 20 | self.entity_type = entity_type 21 | self.entity_id = entity_id 22 | -------------------------------------------------------------------------------- /labellab-flask/api/models/Notification.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | from flask import current_app 3 | 4 | from api.extensions import db, Base 5 | 6 | class Notification(db.Model): 7 | """ 8 | This model holds information about a notification 9 | """ 10 | __tablename__ = "notification" 11 | 12 | id = db.Column(db.Integer, primary_key=True) 13 | message = db.Column(db.String(200), nullable=False) 14 | user_id = db.Column(db.Integer,db.ForeignKey('user.id', ondelete="cascade", onupdate="cascade"), nullable=False) 15 | type = db.Column(db.String(50), nullable=False) 16 | 17 | def __init__(self, message, user_id, type): 18 | self.message = message 19 | self.user_id = user_id 20 | self.type = type 21 | 22 | def __repr__(self): 23 | """ 24 | Returns the object representation 25 | """ 26 | return "" % self.message 27 | -------------------------------------------------------------------------------- /labellab-flask/api/models/Point.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | from flask import current_app 3 | 4 | from api.extensions import db, Base 5 | 6 | class Point(db.Model): 7 | """ 8 | This model holds information about the point of a particular 9 | label to an image. 10 | """ 11 | __tablename__ = "point" 12 | 13 | id = db.Column(db.String(45), primary_key=True) 14 | y_coordinate = db.Column(db.Float, nullable=False) 15 | x_coordinate = db.Column(db.Float, nullable=False) 16 | labeldata_id = db.Column(db.String(45), 17 | db.ForeignKey('labeldata.id', ondelete="cascade", onupdate="cascade"), 18 | nullable=False) 19 | 20 | def __init__(self, id, y_coordinate, x_coordinate, labeldata_id): 21 | """ 22 | Initializes the Point instance 23 | """ 24 | self.id = id 25 | self.labeldata_id = labeldata_id 26 | self.y_coordinate = y_coordinate 27 | self.x_coordinate = x_coordinate 28 | 29 | def __repr__(self): 30 | """ 31 | Returns the object reprensentation 32 | """ 33 | return "" % self.id 34 | -------------------------------------------------------------------------------- /labellab-flask/api/models/ProjectMembers.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | from flask import current_app, jsonify 3 | 4 | from api.extensions import db, Base 5 | 6 | class ProjectMember(db.Model): 7 | """ 8 | This model holds information about a projectmember registered 9 | """ 10 | __tablename__ = "projectmember" 11 | 12 | id = db.Column(db.Integer, primary_key=True) 13 | user_id = db.Column(db.Integer, 14 | db.ForeignKey('user.id', ondelete="cascade", onupdate="cascade"), 15 | nullable=False) 16 | team_id = db.Column(db.Integer, 17 | db.ForeignKey('team.id', ondelete="cascade", onupdate="cascade"), 18 | nullable=False) 19 | 20 | def __init__(self, user_id, team_id): 21 | """ 22 | Initializes the projectMember instance 23 | """ 24 | self.user_id = user_id 25 | self.team_id = team_id 26 | 27 | def __repr__(self): 28 | """ 29 | Returns the object reprensentation 30 | """ 31 | return "" % self.id 32 | -------------------------------------------------------------------------------- /labellab-flask/api/models/RevokedToken.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | from flask import current_app 3 | 4 | from api.extensions import db, Base 5 | 6 | class RevokedToken(db.Model): 7 | """ 8 | This model holds information about revoked tokens, users who have logged out 9 | """ 10 | 11 | __tablename__ = "revoked_token" 12 | id = db.Column(db.Integer, primary_key=True) 13 | jti = db.Column(db.String(120)) 14 | 15 | def add(self): 16 | db.session.add(self) 17 | db.session.commit() 18 | 19 | @classmethod 20 | def is_jti_blacklisted(cls, jti): 21 | query = cls.query.filter_by(jti=jti).first() 22 | return bool(query) -------------------------------------------------------------------------------- /labellab-flask/api/models/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scorelab/LabelLab/080a7cc7fa5a32b042535b1e1214b60bf5881501/labellab-flask/api/models/__init__.py -------------------------------------------------------------------------------- /labellab-flask/api/routes/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scorelab/LabelLab/080a7cc7fa5a32b042535b1e1214b60bf5881501/labellab-flask/api/routes/__init__.py -------------------------------------------------------------------------------- /labellab-flask/api/routes/analytics.py: -------------------------------------------------------------------------------- 1 | from flask import Blueprint 2 | 3 | from api.controllers import analyticscontroller 4 | 5 | analyticsprint = Blueprint("analytics", __name__) 6 | 7 | analyticsprint.add_url_rule( 8 | "/time_label/get/", 9 | view_func=analyticscontroller.analyticsController["time_label"], 10 | methods=["GET"] 11 | ) 12 | 13 | analyticsprint.add_url_rule( 14 | "/label_counts/get/", 15 | view_func=analyticscontroller.analyticsController["label_counts"], 16 | methods=["GET"] 17 | ) 18 | 19 | analyticsprint.add_url_rule( 20 | "/issue_analytics/get/", 21 | view_func=analyticscontroller.analyticsController["issue_analytics"], 22 | methods=["GET"] 23 | ) 24 | -------------------------------------------------------------------------------- /labellab-flask/api/routes/chatroom.py: -------------------------------------------------------------------------------- 1 | from flask import Blueprint 2 | 3 | from api.controllers import chatroomcontroller 4 | 5 | chatroomprint = Blueprint('chatroom', __name__) 6 | 7 | chatroomprint.add_url_rule( 8 | '/chatroom/', 9 | view_func=chatroomcontroller.chatroom_controller['get_messages'], 10 | methods=["GET"] 11 | ) -------------------------------------------------------------------------------- /labellab-flask/api/routes/classifications.py: -------------------------------------------------------------------------------- 1 | from flask import Blueprint 2 | 3 | from api.controllers import classificationscontroller 4 | 5 | classificationsprint = Blueprint("classifications", __name__) 6 | 7 | classificationsprint.add_url_rule( 8 | "/classification/classify", 9 | view_func=classificationscontroller.classificationController["classify_image"], 10 | methods=["POST"]) 11 | 12 | classificationsprint.add_url_rule( 13 | "/classification/get/", 14 | view_func=classificationscontroller.classificationController["get_classification"], 15 | methods=["GET"]) 16 | 17 | classificationsprint.add_url_rule( 18 | "/classification/all", 19 | view_func=classificationscontroller.classificationController["get_all_classifications"], 20 | methods=["GET"]) 21 | 22 | classificationsprint.add_url_rule( 23 | "/classification/delete/", 24 | view_func=classificationscontroller.classificationController["delete_classification"], 25 | methods=["DELETE"]) 26 | -------------------------------------------------------------------------------- /labellab-flask/api/routes/comments.py: -------------------------------------------------------------------------------- 1 | from flask import Blueprint 2 | 3 | from api.controllers import commentcontroller 4 | 5 | commentsprint = Blueprint("comments", __name__) 6 | 7 | commentsprint.add_url_rule( 8 | "/comment/create/", 9 | view_func=commentcontroller.commentController["add_comment"], 10 | methods=["POST"] 11 | ) 12 | 13 | commentsprint.add_url_rule( 14 | "/comment/get/", 15 | view_func=commentcontroller.commentController["get_all_comment"], 16 | methods=["GET"] 17 | ) 18 | 19 | commentsprint.add_url_rule( 20 | "/comment/comment_info//", 21 | view_func=commentcontroller.commentController["comment"], 22 | methods=["GET","DELETE","PUT"] 23 | ) -------------------------------------------------------------------------------- /labellab-flask/api/routes/images.py: -------------------------------------------------------------------------------- 1 | from flask import Blueprint 2 | 3 | from api.controllers import imagescontroller 4 | 5 | imagesprint = Blueprint("images", __name__) 6 | 7 | imagesprint.add_url_rule( 8 | "/image/create/", 9 | view_func=imagescontroller.imageController["save_image"], 10 | methods=["POST"] 11 | ) 12 | 13 | imagesprint.add_url_rule( 14 | "/image/get/", 15 | view_func=imagescontroller.imageController["get_all_images"], 16 | methods=["GET"] 17 | ) 18 | 19 | imagesprint.add_url_rule( 20 | "/image/get_image//", 21 | view_func=imagescontroller.imageController["get_image"], 22 | methods=["GET"] 23 | ) 24 | 25 | imagesprint.add_url_rule( 26 | "/image/delete/", 27 | view_func=imagescontroller.imageController["delete_images"], 28 | methods=["POST"] 29 | ) 30 | 31 | imagesprint.add_url_rule( 32 | "/image/update/", 33 | view_func=imagescontroller.imageController["update_labels"], 34 | methods=["PUT"] 35 | ) -------------------------------------------------------------------------------- /labellab-flask/api/routes/labels.py: -------------------------------------------------------------------------------- 1 | from flask import Blueprint 2 | 3 | from api.controllers import labelscontroller 4 | 5 | labelsprint = Blueprint("labels", __name__) 6 | 7 | labelsprint.add_url_rule( 8 | "/label/create/", 9 | view_func=labelscontroller.labelController["create_label"], 10 | methods=["POST"] 11 | ) 12 | 13 | labelsprint.add_url_rule( 14 | "/label/get/", 15 | view_func=labelscontroller.labelController["get_all_labels"], 16 | methods=["GET"] 17 | ) 18 | 19 | labelsprint.add_url_rule( 20 | "/label/label_info//", 21 | view_func=labelscontroller.labelController["label"], 22 | methods=["GET","DELETE","PUT"] 23 | ) -------------------------------------------------------------------------------- /labellab-flask/api/routes/logs.py: -------------------------------------------------------------------------------- 1 | from flask import Blueprint 2 | 3 | from api.controllers.logscontroller import logs_controller 4 | 5 | logs_blueprint = Blueprint("logs", __name__) 6 | 7 | logs_blueprint.add_url_rule( 8 | '/logs/', 9 | view_func=logs_controller['fetch_project_logs'], 10 | methods=['GET'], 11 | ) 12 | 13 | logs_blueprint.add_url_rule( 14 | '/logs//category/', 15 | view_func=logs_controller['fetch_category_logs'], 16 | methods=['GET'], 17 | ) 18 | 19 | logs_blueprint.add_url_rule( 20 | '/logs//user/', 21 | view_func=logs_controller['fetch_user_logs'], 22 | methods=['GET'], 23 | ) 24 | 25 | logs_blueprint.add_url_rule( 26 | '/logs//entity//', 27 | view_func=logs_controller['fetch_entity_logs'], 28 | methods=['GET'], 29 | ) -------------------------------------------------------------------------------- /labellab-flask/api/routes/ml_files.py: -------------------------------------------------------------------------------- 1 | import os 2 | from flask import Blueprint, render_template, send_from_directory 3 | 4 | from api.config import config 5 | 6 | mlfilesprint = Blueprint("ml_files", __name__) 7 | 8 | def ml_files_route(filename, folder): 9 | if filename != "" and os.path.exists(config['development'].ML_FILES_DIR + '/' + folder + '/' + filename): 10 | return send_from_directory(config['development'].ML_FILES_DIR + '/' + folder, filename) 11 | else: 12 | return render_template('index.html') 13 | 14 | mlfilesprint.add_url_rule( 15 | "//", 16 | view_func=ml_files_route, 17 | methods=["GET"] 18 | ) 19 | -------------------------------------------------------------------------------- /labellab-flask/api/routes/notifications.py: -------------------------------------------------------------------------------- 1 | from flask import Blueprint 2 | 3 | from api.controllers.notificationscontroller import notifications_controller 4 | 5 | notificationsprint = Blueprint("notifications", __name__) 6 | 7 | notificationsprint.add_url_rule( 8 | '/notifications', 9 | view_func=notifications_controller['fetch_user_notifications'], 10 | methods=['GET'], 11 | ) -------------------------------------------------------------------------------- /labellab-flask/api/routes/static.py: -------------------------------------------------------------------------------- 1 | import os 2 | from flask import Blueprint, render_template, send_from_directory 3 | 4 | from api.config import config 5 | 6 | staticprint = Blueprint("static", __name__) 7 | 8 | 9 | def static_route(filename, folder): 10 | if filename != "" and os.path.exists(config['development'].UPLOAD_FOLDER + '/' + str(folder) + '/' + filename): 11 | return send_from_directory(config['development'].UPLOAD_FOLDER + '/' + str(folder), filename) 12 | else: 13 | return render_template('index.html') 14 | 15 | 16 | def static_classifications_route(filename, folder): 17 | if filename != "" and os.path.exists(config['development'].UPLOAD_FOLDER + '/classifications/' + str(folder) + '/' + filename): 18 | return send_from_directory(config['development'].UPLOAD_FOLDER + '/classifications/' + str(folder), filename) 19 | else: 20 | return render_template('index.html') 21 | 22 | 23 | staticprint.add_url_rule( 24 | "//", 25 | view_func=static_route, 26 | methods=["GET"] 27 | ) 28 | 29 | staticprint.add_url_rule( 30 | "/classifications//", 31 | view_func=static_classifications_route, 32 | methods=["GET"] 33 | ) 34 | -------------------------------------------------------------------------------- /labellab-flask/api/routes/teams.py: -------------------------------------------------------------------------------- 1 | from flask import Blueprint 2 | 3 | from api.controllers import teamscontroller 4 | 5 | teamsprint = Blueprint("teams", __name__) 6 | 7 | teamsprint.add_url_rule( 8 | "/team/get/", 9 | view_func=teamscontroller.teamController["get_all_teams"], 10 | methods=["GET"] 11 | ) 12 | 13 | teamsprint.add_url_rule( 14 | "/team/team_info//", 15 | view_func=teamscontroller.teamController["team"], 16 | methods=["GET","DELETE","PUT"] 17 | ) 18 | 19 | teamsprint.add_url_rule( 20 | "/team/add_team_member//", 21 | view_func=teamscontroller.teamController["add_team_member"], 22 | methods=["POST"] 23 | ) 24 | 25 | teamsprint.add_url_rule( 26 | "/team/remove_team_member//", 27 | view_func=teamscontroller.teamController["remove_team_member"], 28 | methods=["POST"] 29 | ) -------------------------------------------------------------------------------- /labellab-flask/api/serializers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scorelab/LabelLab/080a7cc7fa5a32b042535b1e1214b60bf5881501/labellab-flask/api/serializers/__init__.py -------------------------------------------------------------------------------- /labellab-flask/api/serializers/classification.py: -------------------------------------------------------------------------------- 1 | from marshmallow import Schema, fields 2 | 3 | from api.extensions import db, ma 4 | 5 | 6 | class ClassificationSchema(ma.ModelSchema): 7 | # Serializer for Classification 8 | 9 | id = fields.Int(dump_only=True) 10 | image_name = fields.Str() 11 | image_url = fields.Str() 12 | label = fields.Str() 13 | confidence = fields.Float() 14 | user_id = fields.Int(dump_only=True) 15 | classified_at = fields.DateTime() 16 | -------------------------------------------------------------------------------- /labellab-flask/api/serializers/comment.py: -------------------------------------------------------------------------------- 1 | from marshmallow import Schema, fields 2 | 3 | from api.extensions import db, ma 4 | 5 | class CommentSchema(ma.ModelSchema): 6 | """ 7 | Serializer class for Comments 8 | """ 9 | 10 | id = fields.Int(dump_only=True) 11 | body = fields.Str() 12 | issue_id = fields.Int(dump_only=True) 13 | user_id = fields.Int(dump_only=True) 14 | username=fields.Str(dump_only=True) 15 | thumbnail = fields.Str() 16 | timestamp = fields.DateTime(format='%Y-%m-%d %H:%M:%S', dump_only=True) 17 | 18 | -------------------------------------------------------------------------------- /labellab-flask/api/serializers/image.py: -------------------------------------------------------------------------------- 1 | from marshmallow import Schema, fields 2 | 3 | from api.extensions import db, ma 4 | from api.serializers.labeldata import LabelDataSchema 5 | 6 | class ImageSchema(ma.ModelSchema): 7 | """ 8 | Serializer class for image 9 | """ 10 | 11 | id = fields.Int(dump_only=True) 12 | image_name = fields.Str() 13 | image_url = fields.Str() 14 | height = fields.Int() 15 | width = fields.Int() 16 | labelled = fields.Bool() 17 | project_id = fields.Int(dump_only=True) 18 | labeldata = fields.Nested(LabelDataSchema, many=True) -------------------------------------------------------------------------------- /labellab-flask/api/serializers/issue.py: -------------------------------------------------------------------------------- 1 | from marshmallow import Schema, fields 2 | 3 | from api.extensions import db, ma 4 | 5 | class IssueSchema(ma.ModelSchema): 6 | """ 7 | Serializer class for issue 8 | """ 9 | 10 | id = fields.Int(dump_only=True) 11 | title = fields.Str() 12 | description = fields.Str() 13 | project_id = fields.Int(dump_only=True) 14 | created_by = fields.Int(dump_only=True) 15 | assignee_id = fields.Int() 16 | team_id = fields.Int() 17 | category = fields.Str() 18 | priority = fields.Str() 19 | status = fields.Str() 20 | entity_type = fields.Str() 21 | entity_id = fields.Int() 22 | due_date = fields.DateTime(format='%Y-%m-%d %H:%M:%S') 23 | created_at = fields.DateTime(format='%Y-%m-%d %H:%M:%S', dump_only=True) 24 | updated_at = fields.DateTime(format='%Y-%m-%d %H:%M:%S') 25 | -------------------------------------------------------------------------------- /labellab-flask/api/serializers/label.py: -------------------------------------------------------------------------------- 1 | from marshmallow import Schema, fields 2 | 3 | from api.extensions import db, ma 4 | from api.serializers.labeldata import LabelDataSchema 5 | 6 | class LabelSchema(ma.ModelSchema): 7 | """ 8 | Serializer class for label 9 | """ 10 | 11 | id = fields.Int(dump_only=True) 12 | label_name = fields.Str() 13 | label_type = fields.Str() 14 | count = fields.Int() 15 | project_id = fields.Int(dump_only=True) 16 | created_at = fields.DateTime(format='%Y-%m-%d %H:%M:%S', dump_only=True) 17 | labeldata = fields.Nested(LabelDataSchema, many=True) 18 | -------------------------------------------------------------------------------- /labellab-flask/api/serializers/labeldata.py: -------------------------------------------------------------------------------- 1 | from marshmallow import Schema, fields, post_dump 2 | 3 | from api.extensions import db, ma 4 | from api.serializers.point import PointSchema 5 | 6 | class LabelDataSchema(ma.ModelSchema): 7 | """ 8 | Serializer class for labeldata 9 | """ 10 | 11 | id = fields.Str(dump_only=True) 12 | months_passed = fields.Int() 13 | image_id = fields.Int(dump_only=True) 14 | label_id = fields.Int(dump_only=True) 15 | points = fields.Nested(PointSchema, many=True) 16 | 17 | @post_dump(pass_many=True) 18 | def data(self, data, many, **kwargs): 19 | from api.helpers.label import get_label_type 20 | res_data = {} 21 | try: 22 | for i in range(len(data)): 23 | if res_data.get(data[i]['label_id']) is None: 24 | res_data[data[i]['label_id']] = [] 25 | label_type = get_label_type(data[i]['label_id']) 26 | data[i]['label_type'] = label_type 27 | res_data[data[i]['label_id']].append(data[i]) 28 | return res_data 29 | except Exception as err: 30 | print(err) 31 | -------------------------------------------------------------------------------- /labellab-flask/api/serializers/mlclassifier.py: -------------------------------------------------------------------------------- 1 | from marshmallow import Schema, fields 2 | 3 | from api.extensions import db, ma 4 | from api.serializers.label import LabelSchema 5 | 6 | class MLClassifierSchema(ma.ModelSchema): 7 | """ 8 | Serializer class for ML Classifier 9 | """ 10 | 11 | id = fields.Int(dump_only=True) 12 | name = fields.Str() 13 | type = fields.Str() 14 | source = fields.Str() 15 | preprocessing_steps_json_url = fields.Str() 16 | layers_json_url = fields.Str() 17 | train = fields.Float() 18 | test = fields.Float() 19 | validation = fields.Float() 20 | epochs = fields.Int() 21 | batch_size = fields.Int() 22 | learning_rate = fields.Float() 23 | loss = fields.Str() 24 | optimizer = fields.Str() 25 | metric = fields.Str() 26 | loss_graph_url = fields.Str() 27 | accuracy_graph_url = fields.Str() 28 | saved_model_url = fields.Str() 29 | transfer_source = fields.Str() 30 | project_id = fields.Int(dump_only=True) 31 | labels = fields.Nested(LabelSchema, many=True) -------------------------------------------------------------------------------- /labellab-flask/api/serializers/notification.py: -------------------------------------------------------------------------------- 1 | from marshmallow import Schema, fields 2 | 3 | from api.extensions import db, ma 4 | 5 | class NotificationSchema(ma.ModelSchema): 6 | """ 7 | Serializer class for Notifications 8 | """ 9 | id = fields.Int(dump_only=True) 10 | message = fields.Str() 11 | type = fields.Str() 12 | user_id = fields.Int(dump_only=True) 13 | -------------------------------------------------------------------------------- /labellab-flask/api/serializers/point.py: -------------------------------------------------------------------------------- 1 | from marshmallow import Schema, fields 2 | 3 | from api.extensions import db, ma 4 | 5 | class PointSchema(ma.ModelSchema): 6 | """ 7 | Serializer class for Point 8 | """ 9 | 10 | id = fields.Str(dump_only=True) 11 | lng = fields.Float(attribute="y_coordinate") 12 | lat = fields.Float(attribute="x_coordinate") 13 | labeldata_id = fields.Str(dump_only=True) -------------------------------------------------------------------------------- /labellab-flask/api/serializers/project.py: -------------------------------------------------------------------------------- 1 | from marshmallow import Schema, fields 2 | 3 | from api.extensions import db, ma 4 | from api.serializers.image import ImageSchema 5 | from api.serializers.label import LabelSchema 6 | from api.serializers.issue import IssueSchema 7 | 8 | class ProjectSchema(ma.ModelSchema): 9 | """ 10 | Serializer class for project 11 | """ 12 | 13 | id = fields.Int(dump_only=True) 14 | project_name = fields.Str() 15 | project_description = fields.Str() 16 | admin_id = fields.Int(dump_only=True) 17 | images = fields.Nested(ImageSchema, many=True) 18 | labels = fields.Nested(LabelSchema, many=True) 19 | issues = fields.Nested(IssueSchema, many=True) 20 | -------------------------------------------------------------------------------- /labellab-flask/api/serializers/projectmember.py: -------------------------------------------------------------------------------- 1 | from marshmallow import Schema, fields 2 | 3 | from api.extensions import ma 4 | 5 | class ProjectMemberSchema(ma.ModelSchema): 6 | """ 7 | Serializer class for projectmember 8 | """ 9 | 10 | user_id = fields.Int(dump_only=True) 11 | team_id = fields.Int(dump_only=True) 12 | -------------------------------------------------------------------------------- /labellab-flask/api/serializers/team.py: -------------------------------------------------------------------------------- 1 | from marshmallow import Schema, fields 2 | 3 | from api.extensions import db, ma 4 | from api.serializers.projectmember import ProjectMemberSchema 5 | 6 | class TeamSchema(ma.ModelSchema): 7 | """ 8 | Serializer class for team 9 | """ 10 | 11 | id = fields.Int(dump_only=True) 12 | team_name = fields.Str() 13 | role = fields.Str() 14 | project_id = fields.Int(dump_only=True) 15 | team_members = fields.Nested(ProjectMemberSchema, many=True) -------------------------------------------------------------------------------- /labellab-flask/api/serializers/user.py: -------------------------------------------------------------------------------- 1 | from marshmallow import Schema, fields 2 | 3 | from api.extensions import ma 4 | from api.serializers.project import ProjectSchema 5 | from api.serializers.projectmember import ProjectMemberSchema 6 | 7 | class UserSchema(ma.ModelSchema): 8 | """ 9 | Serializer class for user 10 | """ 11 | 12 | id = fields.Int(dump_only=True) 13 | name = fields.Str() 14 | username = fields.Str() 15 | email = fields.Str() 16 | thumbnail = fields.Str() 17 | projects = fields.Nested(ProjectSchema, many=True) 18 | project_members = fields.Nested(ProjectMemberSchema, many=True) 19 | -------------------------------------------------------------------------------- /labellab-flask/app.py: -------------------------------------------------------------------------------- 1 | import os 2 | from dotenv import load_dotenv 3 | from flask import render_template 4 | 5 | import sys 6 | sys.path.insert(0,os.getcwd()) 7 | dotenv_path = os.path.join(os.path.dirname(__file__), ".env") 8 | if os.path.exists(dotenv_path): 9 | load_dotenv(dotenv_path) 10 | 11 | from api.main import create_app 12 | from api.extensions import socketio 13 | 14 | app = create_app(os.getenv("FLASK_CONFIG") or "default") 15 | 16 | @app.route("/", defaults={"path": ""}) 17 | @app.route("/") 18 | def default_route(path): 19 | return render_template('index.html') 20 | 21 | if __name__ == "__main__": 22 | socketio.run(app, host='0.0.0.0', port=5000, debug=True) 23 | -------------------------------------------------------------------------------- /labellab-flask/app.yaml: -------------------------------------------------------------------------------- 1 | runtime: python37 2 | entrypoint: gunicorn -b :$PORT app:app -------------------------------------------------------------------------------- /labellab-flask/boot.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec flask run -------------------------------------------------------------------------------- /labellab-flask/docker.txt: -------------------------------------------------------------------------------- 1 | -r requirements.txt -------------------------------------------------------------------------------- /labellab-flask/docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = source 9 | BUILDDIR = build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /labellab-flask/docs/labellab-flask.rst: -------------------------------------------------------------------------------- 1 | labellab\-flask package 2 | ======================= 3 | 4 | Subpackages 5 | ----------- 6 | 7 | .. toctree:: 8 | :maxdepth: 4 9 | 10 | labellab-flask.api 11 | labellab-flask.tests 12 | 13 | Submodules 14 | ---------- 15 | 16 | labellab\-flask.app module 17 | -------------------------- 18 | 19 | .. automodule:: labellab-flask.app 20 | :members: 21 | :undoc-members: 22 | :show-inheritance: 23 | 24 | Module contents 25 | --------------- 26 | 27 | .. automodule:: labellab-flask 28 | :members: 29 | :undoc-members: 30 | :show-inheritance: 31 | -------------------------------------------------------------------------------- /labellab-flask/docs/labellab-flask.tests.rst: -------------------------------------------------------------------------------- 1 | labellab\-flask.tests package 2 | ============================= 3 | 4 | Submodules 5 | ---------- 6 | 7 | labellab\-flask.tests.test\_login module 8 | ---------------------------------------- 9 | 10 | .. automodule:: labellab-flask.tests.test_login 11 | :members: 12 | :undoc-members: 13 | :show-inheritance: 14 | 15 | labellab\-flask.tests.test\_project module 16 | ------------------------------------------ 17 | 18 | .. automodule:: labellab-flask.tests.test_project 19 | :members: 20 | :undoc-members: 21 | :show-inheritance: 22 | 23 | labellab\-flask.tests.test\_register module 24 | ------------------------------------------- 25 | 26 | .. automodule:: labellab-flask.tests.test_register 27 | :members: 28 | :undoc-members: 29 | :show-inheritance: 30 | 31 | Module contents 32 | --------------- 33 | 34 | .. automodule:: labellab-flask.tests 35 | :members: 36 | :undoc-members: 37 | :show-inheritance: 38 | -------------------------------------------------------------------------------- /labellab-flask/docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=source 11 | set BUILDDIR=build 12 | 13 | if "%1" == "" goto help 14 | 15 | %SPHINXBUILD% >NUL 2>NUL 16 | if errorlevel 9009 ( 17 | echo. 18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 19 | echo.installed, then set the SPHINXBUILD environment variable to point 20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 21 | echo.may add the Sphinx directory to PATH. 22 | echo. 23 | echo.If you don't have Sphinx installed, grab it from 24 | echo.http://sphinx-doc.org/ 25 | exit /b 1 26 | ) 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /labellab-flask/docs/modules.rst: -------------------------------------------------------------------------------- 1 | labellab-flask 2 | ============== 3 | 4 | .. toctree:: 5 | :maxdepth: 4 6 | 7 | labellab-flask 8 | -------------------------------------------------------------------------------- /labellab-flask/docs/source/index.rst: -------------------------------------------------------------------------------- 1 | .. Labellab-Flask documentation master file, created by 2 | sphinx-quickstart on Sat Aug 15 22:57:00 2020. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Welcome to Labellab-Flask's documentation! 7 | ========================================== 8 | 9 | .. toctree:: 10 | :maxdepth: 2 11 | :caption: Contents: 12 | 13 | 14 | 15 | Indices and tables 16 | ================== 17 | 18 | * :ref:`genindex` 19 | * :ref:`modindex` 20 | * :ref:`search` 21 | -------------------------------------------------------------------------------- /labellab-flask/migrations/README: -------------------------------------------------------------------------------- 1 | Generic single-database configuration. -------------------------------------------------------------------------------- /labellab-flask/migrations/alembic.ini: -------------------------------------------------------------------------------- 1 | # A generic, single database configuration. 2 | 3 | [alembic] 4 | # template used to generate migration files 5 | # file_template = %%(rev)s_%%(slug)s 6 | 7 | # set to 'true' to run the environment during 8 | # the 'revision' command, regardless of autogenerate 9 | # revision_environment = false 10 | 11 | 12 | # Logging configuration 13 | [loggers] 14 | keys = root,sqlalchemy,alembic 15 | 16 | [handlers] 17 | keys = console 18 | 19 | [formatters] 20 | keys = generic 21 | 22 | [logger_root] 23 | level = WARN 24 | handlers = console 25 | qualname = 26 | 27 | [logger_sqlalchemy] 28 | level = WARN 29 | handlers = 30 | qualname = sqlalchemy.engine 31 | 32 | [logger_alembic] 33 | level = INFO 34 | handlers = 35 | qualname = alembic 36 | 37 | [handler_console] 38 | class = StreamHandler 39 | args = (sys.stderr,) 40 | level = NOTSET 41 | formatter = generic 42 | 43 | [formatter_generic] 44 | format = %(levelname)-5.5s [%(name)s] %(message)s 45 | datefmt = %H:%M:%S 46 | -------------------------------------------------------------------------------- /labellab-flask/migrations/script.py.mako: -------------------------------------------------------------------------------- 1 | """${message} 2 | 3 | Revision ID: ${up_revision} 4 | Revises: ${down_revision | comma,n} 5 | Create Date: ${create_date} 6 | 7 | """ 8 | from alembic import op 9 | import sqlalchemy as sa 10 | ${imports if imports else ""} 11 | 12 | # revision identifiers, used by Alembic. 13 | revision = ${repr(up_revision)} 14 | down_revision = ${repr(down_revision)} 15 | branch_labels = ${repr(branch_labels)} 16 | depends_on = ${repr(depends_on)} 17 | 18 | 19 | def upgrade(): 20 | ${upgrades if upgrades else "pass"} 21 | 22 | 23 | def downgrade(): 24 | ${downgrades if downgrades else "pass"} 25 | -------------------------------------------------------------------------------- /labellab-flask/path_tracking/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scorelab/LabelLab/080a7cc7fa5a32b042535b1e1214b60bf5881501/labellab-flask/path_tracking/__init__.py -------------------------------------------------------------------------------- /labellab-flask/path_tracking/sample6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scorelab/LabelLab/080a7cc7fa5a32b042535b1e1214b60bf5881501/labellab-flask/path_tracking/sample6.png -------------------------------------------------------------------------------- /labellab-flask/pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: https://github.com/ambv/black 3 | rev: stable 4 | hooks: 5 | - id: black 6 | language_version: python3.6 7 | - repo: https://github.com/pre-commit/pre-commit-hooks 8 | rev: v1.2.3 9 | hooks: 10 | - id: flake8 -------------------------------------------------------------------------------- /labellab-flask/prod.txt: -------------------------------------------------------------------------------- 1 | -r requirements.txt 2 | gunicorn==20.0.4 -------------------------------------------------------------------------------- /labellab-flask/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scorelab/LabelLab/080a7cc7fa5a32b042535b1e1214b60bf5881501/labellab-flask/tests/__init__.py -------------------------------------------------------------------------------- /labellab-flask/uploads/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore everything in this directory 2 | * 3 | # Except this file 4 | !.gitignore -------------------------------------------------------------------------------- /labellab-server/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | npm-debug.log 3 | Dockerfile* 4 | docker-compose* 5 | .dockerignore 6 | .git 7 | .gitignore 8 | .env 9 | */bin 10 | */obj 11 | README.md 12 | LICENSE 13 | .vscode -------------------------------------------------------------------------------- /labellab-server/.env.example: -------------------------------------------------------------------------------- 1 | HOST= 2 | PORT= 3 | JWT_SECRET= 4 | DB_HOST= 5 | DB_NAME= 6 | DB_CLUSTER= 7 | DB_USERNAME= 8 | DB_PASSWORD= 9 | GOOGLE_CLIENT_ID= 10 | GOOGLE_CLIENT_SECRET= 11 | GITHUB_CLIENT_ID= 12 | GITHUB_CLIENT_SECRET= 13 | EMAIL_PASSWORD = 14 | EMAIL_ADDRESS = 15 | REACT_APP_HOST= -------------------------------------------------------------------------------- /labellab-server/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "node": true, 4 | "browser": true, 5 | "commonjs": true, 6 | "es6": true 7 | }, 8 | "extends": "eslint:recommended", 9 | "parserOptions": { 10 | "ecmaVersion": 2018, 11 | "sourceType": "module" 12 | }, 13 | "rules": { 14 | "no-unused-vars": ["off", { "vars": "all", "args": "after-used", "ignoreRestSiblings": false }], 15 | "no-console": "off", 16 | "indent": [ 17 | "error", 18 | "tab" 19 | ], 20 | "linebreak-style": [ 21 | "error", 22 | "unix" 23 | ], 24 | "quotes": [ 25 | "error", 26 | "single" 27 | ], 28 | "semi": [ 29 | "error", 30 | "never" 31 | ] 32 | } 33 | } -------------------------------------------------------------------------------- /labellab-server/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node 2 | 3 | RUN mkdir -p /usr/labellab/labellab-server 4 | WORKDIR /usr/labellab/labellab-server 5 | 6 | COPY package.json /usr/labellab/labellab-server 7 | RUN npm install 8 | COPY . /usr/labellab/labellab-server 9 | EXPOSE 4000 10 | CMD ["npm", "start"] -------------------------------------------------------------------------------- /labellab-server/config/dbURI.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | require('dotenv').config() 3 | 4 | var dbHost = process.env.DB_HOST || 'localhost' 5 | var dbName = process.env.DB_NAME 6 | var dbCluster = process.env.DB_CLUSTER 7 | var dbUser = process.env.DB_USERNAME 8 | var dbPass = process.env.DB_PASSWORD 9 | 10 | let mongoURI 11 | 12 | if (dbName && dbUser && dbPass) { 13 | mongoURI = 14 | '' + dbHost + '://' + dbUser + ':' + dbPass + '@' + dbCluster + '/' + dbName 15 | } else if (process.env.MONGODB_URI) { 16 | mongoURI = process.env.MONGODB_URI 17 | } else { 18 | mongoURI = '' 19 | } 20 | 21 | module.exports = { 22 | mongoURI: mongoURI, 23 | } 24 | -------------------------------------------------------------------------------- /labellab-server/config/jwtSecret.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | require('dotenv').config() 3 | 4 | var jwtSecret = process.env.JWT_SECRET 5 | 6 | if(!jwtSecret){ 7 | jwtSecret = 'JWTSECRET' 8 | } 9 | 10 | module.exports = { 11 | jwtSecret:jwtSecret 12 | } -------------------------------------------------------------------------------- /labellab-server/controller/auth/oauth.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | require('dotenv').config() 3 | 4 | const jwt = require('jwt-simple') 5 | const secret = require('../../config/jwtSecret').jwtSecret 6 | 7 | function createtoken(user) { 8 | const timestamp = new Date().getTime() 9 | return jwt.encode({ sub: user.id, iat: timestamp }, secret) 10 | } 11 | 12 | module.exports.signin = function signin(req, res, next) { 13 | res.render('authenticated.ejs', { token: createtoken(req.user) }) 14 | } 15 | -------------------------------------------------------------------------------- /labellab-server/models/classification.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose') 2 | 3 | const ClassificationSchema = new mongoose.Schema({ 4 | user: { 5 | type: mongoose.Schema.Types.ObjectId, 6 | ref: 'User' 7 | }, 8 | imageUrl: { 9 | type: String, 10 | required: true 11 | }, 12 | label: [ 13 | { 14 | type: Object 15 | } 16 | ], 17 | createdAt: { 18 | type: Date, 19 | default: Date.now 20 | } 21 | }) 22 | 23 | module.exports = mongoose.model('Classification', ClassificationSchema) 24 | -------------------------------------------------------------------------------- /labellab-server/models/image.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose') 2 | 3 | const ImageSchema = new mongoose.Schema({ 4 | project: { 5 | type: mongoose.Schema.Types.ObjectId, 6 | ref: 'Project' 7 | }, 8 | imageName: { 9 | type: String, 10 | required: true 11 | }, 12 | imageUrl: { 13 | type: String, 14 | required: true 15 | }, 16 | labelData: { 17 | type: Object 18 | }, 19 | height: { 20 | type: Number 21 | }, 22 | width: { 23 | type: Number 24 | }, 25 | labelled: { 26 | type: Boolean, 27 | default: false 28 | }, 29 | createdAt: { 30 | type: Date, 31 | default: Date.now 32 | } 33 | }) 34 | 35 | module.exports = mongoose.model('Image', ImageSchema) 36 | -------------------------------------------------------------------------------- /labellab-server/models/label.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose') 2 | 3 | var LabelSchema = new mongoose.Schema({ 4 | project: { 5 | type: mongoose.Schema.Types.ObjectId, 6 | ref: 'Project' 7 | }, 8 | id: { 9 | type: String, 10 | unique: true 11 | }, 12 | name: { 13 | type: String 14 | }, 15 | type: { 16 | type: String 17 | }, 18 | createdAt: { 19 | type: Date, 20 | default: Date.now 21 | }, 22 | count: { 23 | type: Number, 24 | required: false, 25 | default: 0 26 | } 27 | }) 28 | 29 | module.exports = mongoose.model('Label', LabelSchema) 30 | -------------------------------------------------------------------------------- /labellab-server/models/project.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose') 2 | 3 | const ProjectSchema = new mongoose.Schema({ 4 | user: { 5 | type: mongoose.Schema.Types.ObjectId, 6 | ref: 'User' 7 | }, 8 | projectName: { 9 | type: String, 10 | required: true 11 | }, 12 | projectDescription: { 13 | type: String, 14 | default: 'Image labelling' 15 | }, 16 | createdAt: { 17 | type: Date, 18 | default: Date.now 19 | }, 20 | image: [ 21 | { 22 | type: mongoose.Schema.Types.ObjectId, 23 | ref: 'Image' 24 | } 25 | ], 26 | members: [ 27 | { 28 | type: mongoose.Schema.Types.ObjectId, 29 | ref: 'ProjectMembers' 30 | } 31 | ], 32 | labels: [ 33 | { 34 | type: mongoose.Schema.Types.ObjectId, 35 | ref: 'Label' 36 | } 37 | ] 38 | }) 39 | 40 | module.exports = mongoose.model('Project', ProjectSchema) 41 | -------------------------------------------------------------------------------- /labellab-server/models/projectMembers.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose') 2 | 3 | const ProjectMembersSchema = new mongoose.Schema({ 4 | member: { 5 | type: mongoose.Schema.Types.ObjectId, 6 | ref: 'User' 7 | }, 8 | projectId: { 9 | type: mongoose.Schema.Types.ObjectId, 10 | ref: 'Project' 11 | }, 12 | createdAt: { 13 | type: Date, 14 | default: Date.now 15 | }, 16 | role: { 17 | type: String, 18 | default: 'Member' 19 | } 20 | }) 21 | 22 | module.exports = mongoose.model('ProjectMembers', ProjectMembersSchema) 23 | -------------------------------------------------------------------------------- /labellab-server/public/classifications/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore everything in this directory 2 | * 3 | # Except this file 4 | !.gitignore -------------------------------------------------------------------------------- /labellab-server/public/img/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore everything in this directory 2 | * 3 | # Except this file 4 | !.gitignore -------------------------------------------------------------------------------- /labellab-server/public/project/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore everything in this directory 2 | * 3 | # Except this file 4 | !.gitignore -------------------------------------------------------------------------------- /labellab-server/public/stylesheets/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding: 50px; 3 | font: 14px "Lucida Grande", Helvetica, Arial, sans-serif; 4 | } 5 | 6 | a { 7 | color: #00B7FF; 8 | } 9 | -------------------------------------------------------------------------------- /labellab-server/public/uploads/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore everything in this directory 2 | * 3 | # Except this file 4 | !.gitignore -------------------------------------------------------------------------------- /labellab-server/routes/analytics/routes.js: -------------------------------------------------------------------------------- 1 | var express = require('express') 2 | var passport = require('passport') 3 | const router = express.Router() 4 | const requireAuth = passport.authenticate('jwt', { session: false }) 5 | 6 | // Include controllers of each route 7 | const analyticsControls = require('../../controller/analytics/analyticsControls') 8 | 9 | // GET method 10 | // To fetch time-label dataset of a project 11 | router.get( 12 | '/:projectId/timeLabel/get', 13 | requireAuth, 14 | analyticsControls.timeLabel 15 | ) 16 | 17 | // GET method 18 | // To fetch counts of how often a label is used in a project 19 | router.get( 20 | '/:projectId/labelCount/get', 21 | requireAuth, 22 | analyticsControls.countLabel 23 | ) 24 | 25 | module.exports = router 26 | -------------------------------------------------------------------------------- /labellab-server/routes/classification/routes.js: -------------------------------------------------------------------------------- 1 | var express = require('express') 2 | var passport = require('passport') 3 | const router = express.Router() 4 | const requireAuth = passport.authenticate('jwt', { session: false }) 5 | 6 | // Include controllers of each route 7 | const classificationControls = require('../../controller/classification/classificationControls') 8 | 9 | // POST method 10 | // To process a new classification 11 | router.post('/classify', requireAuth, classificationControls.classify) 12 | 13 | // GET method 14 | // To fetch all classification of the user 15 | router.get('/get', requireAuth, classificationControls.fetchClassification) 16 | 17 | // GET method 18 | // To fetch a classification 19 | router.get('/get/:classificationId', requireAuth, classificationControls.fetchClassificationId) 20 | 21 | // DELETE method 22 | // To delete a classification 23 | router.delete('/delete/:classificationId', requireAuth, classificationControls.deleteClassificationId) 24 | 25 | module.exports = router 26 | -------------------------------------------------------------------------------- /labellab-server/routes/image/routes.js: -------------------------------------------------------------------------------- 1 | var express = require('express') 2 | var passport = require('passport') 3 | const router = express.Router() 4 | const requireAuth = passport.authenticate('jwt', { session: false }) 5 | 6 | // Include controllers of each route 7 | const imageControls = require('../../controller/image/imageControls') 8 | 9 | // POST method 10 | // To post image of a project 11 | router.post('/:projectId/create', requireAuth, imageControls.postImage) 12 | 13 | // GET method 14 | // To fetch a image 15 | router.get('/:imageId/get', requireAuth, imageControls.fetchImageId) 16 | 17 | // PUT method 18 | // To update labelData details 19 | router.put('/:imageId/update', requireAuth, imageControls.updateLabels) 20 | 21 | // DELETE method 22 | // To delete image 23 | router.delete('/delete', requireAuth, imageControls.deleteImage) 24 | 25 | module.exports = router 26 | -------------------------------------------------------------------------------- /labellab-server/routes/label/routes.js: -------------------------------------------------------------------------------- 1 | var express = require('express') 2 | var passport = require('passport') 3 | const router = express.Router() 4 | const requireAuth = passport.authenticate('jwt', { session: false }) 5 | 6 | // Include controllers of each route 7 | const labelControls = require('../../controller/label/labelControls') 8 | 9 | // POST method 10 | // To post label of a project 11 | router.post('/:projectId/create', requireAuth, labelControls.createLabel) 12 | 13 | // PUT method 14 | // To update label of a project 15 | router.put('/:labelId/update', requireAuth, labelControls.updateLabel) 16 | 17 | // GET method 18 | // To fetch labels of a project 19 | router.get('/:projectId/get', requireAuth, labelControls.fetchLabel) 20 | 21 | // DELETE method 22 | // To delete labels of a project 23 | router.delete('/:labelId/delete', requireAuth, labelControls.deleteLabel) 24 | 25 | module.exports = router 26 | -------------------------------------------------------------------------------- /labellab-server/routes/routes.js: -------------------------------------------------------------------------------- 1 | var express = require('express') 2 | var router = express.Router() 3 | 4 | // API's path 5 | var authRoute = require('./auth/routes') 6 | var usersRoute = require('./users/routes') 7 | var projectRoute = require('./project/routes') 8 | var imageRoutes = require('./image/routes') 9 | var labelRoutes = require('./label/routes') 10 | var analyticsRoutes = require('./analytics/routes') 11 | var classificationRoutes = require('./classification/routes') 12 | 13 | // Routes 14 | // -> /api/auth/ 15 | router.use('/api/v1/auth', authRoute) 16 | router.use('/api/v1/users', usersRoute) 17 | router.use('/api/v1/project', projectRoute) 18 | router.use('/api/v1/image', imageRoutes) 19 | router.use('/api/v1/label', labelRoutes) 20 | router.use('/api/v1/analytics', analyticsRoutes) 21 | router.use('/api/v1/classification', classificationRoutes) 22 | 23 | module.exports = router 24 | -------------------------------------------------------------------------------- /labellab-server/routes/users/routes.js: -------------------------------------------------------------------------------- 1 | var express = require('express') 2 | var passport = require('passport') 3 | const router = express.Router() 4 | const requireAuth = passport.authenticate('jwt', { session: false }) 5 | 6 | // Include controllers of each route 7 | const userControls = require('../../controller/user/userControls') 8 | 9 | // GET method 10 | // To fetch user information 11 | router.get('/info', requireAuth, userControls.userInfo) 12 | 13 | // PUT method 14 | // To fetch user information 15 | router.put('/edit', requireAuth, userControls.editInfo) 16 | 17 | // GET method 18 | // To fetch user information of a given user 19 | router.get('/search/:query', requireAuth, userControls.searchUser) 20 | 21 | // GET method 22 | // To fetch user info count 23 | router.get('/fetchCount', requireAuth, userControls.countInfo) 24 | 25 | // POST method 26 | // To upload user image 27 | router.post('/uploadImage', requireAuth, userControls.userUploadImage) 28 | 29 | module.exports = router 30 | -------------------------------------------------------------------------------- /labellab-server/utils/color.js: -------------------------------------------------------------------------------- 1 | const colorData = [ 2 | 'rgba(255, 99, 132, 0.6)', 3 | 'rgba(54, 162, 235, 0.6)', 4 | 'rgba(255, 206, 86, 0.6)', 5 | 'rgba(75, 192, 192, 0.6)', 6 | 'rgba(153, 102, 255, 0.6)', 7 | 'rgba(255, 159, 64, 0.6)', 8 | 'rgba(255, 99, 110, 0.6)', 9 | 'rgba(54, 150, 200, 0.6)', 10 | 'rgba(255, 150, 255, 0.6)', 11 | 'rgba(75, 255, 255, 0.6)', 12 | 'rgba(255, 102, 255, 0.6)', 13 | 'rgba(255, 50, 200, 0.6)', 14 | 'rgba(255, 255, 132, 0.6)' 15 | ] 16 | 17 | exports.getColor = function(num) { 18 | let final = [] 19 | for (let i = 1; i <= num; i++) { 20 | final.push(colorData[i % colorData.length]) 21 | } 22 | return final 23 | } 24 | -------------------------------------------------------------------------------- /labellab-server/utils/error.js: -------------------------------------------------------------------------------- 1 | const handleError = (err, res) => { 2 | const { statusCode, message } = err; 3 | res.status(statusCode).json({ 4 | status: "error", 5 | statusCode, 6 | message 7 | }); 8 | }; 9 | 10 | module.exports = { 11 | handleError 12 | } -------------------------------------------------------------------------------- /labellab-server/utils/labelData.js: -------------------------------------------------------------------------------- 1 | const monthData = [ 2 | 'January', 3 | 'February', 4 | 'March', 5 | 'April', 6 | 'May', 7 | 'June', 8 | 'July', 9 | 'August', 10 | 'September', 11 | 'October', 12 | 'November', 13 | 'December' 14 | ] 15 | exports.getLabelData = function(labelData) { 16 | let final = [] 17 | for (let i = 0; i < 6; i++) { 18 | final.push(0) 19 | } 20 | let currentDate = new Date() 21 | let currentMonth = currentDate.getMonth() 22 | 23 | for (let i = 0; i < labelData.length; i++) { 24 | final[currentMonth - labelData[i]]++ 25 | } 26 | 27 | return final 28 | } 29 | 30 | exports.getLabelCounts = function(labels) { 31 | let countData = { 32 | labels: [], 33 | datasets: [ 34 | { 35 | data: [], 36 | backgroundColor: [], 37 | hoverBackgroundColor: [] 38 | } 39 | ] 40 | } 41 | labels.forEach(label => { 42 | countData.labels.push(label.name) 43 | label.count 44 | ? countData.datasets[0].data.push(label.count) 45 | : countData.datasets[0].data.push(0) 46 | countData.datasets[0].backgroundColor.push( 47 | '#' + ((Math.random() * 0xffffff) << 0).toString(16) 48 | ) 49 | }) 50 | 51 | return countData 52 | } 53 | -------------------------------------------------------------------------------- /labellab-server/utils/months.js: -------------------------------------------------------------------------------- 1 | const monthData = [ 2 | 'January', 3 | 'February', 4 | 'March', 5 | 'April', 6 | 'May', 7 | 'June', 8 | 'July', 9 | 'August', 10 | 'September', 11 | 'October', 12 | 'November', 13 | 'December' 14 | ] 15 | exports.getMonths = function(num) { 16 | let final = [] 17 | let currentDate = new Date() 18 | let currentMonth = currentDate.getMonth() 19 | 20 | for ( 21 | let i = monthData.length + currentMonth; 22 | i > monthData.length + currentMonth - num; 23 | i-- 24 | ) { 25 | final.push(monthData[i % monthData.length]) 26 | } 27 | 28 | return final 29 | } 30 | -------------------------------------------------------------------------------- /labellab-server/utils/randomString.js: -------------------------------------------------------------------------------- 1 | exports.makeid = function(length) { 2 | var result = '' 3 | var characters = 4 | 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789' 5 | var charactersLength = characters.length 6 | for (var i = 0; i < length; i++) { 7 | result += characters.charAt(Math.floor(Math.random() * charactersLength)) 8 | } 9 | return result 10 | } 11 | -------------------------------------------------------------------------------- /labellab-server/views/authenticated.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Authenticated 5 | 6 | 7 | Authenticated successfully. 8 | 9 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /labellab-server/views/error.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Something went wrong! 6 | 7 | 8 | -------------------------------------------------------------------------------- /labellab_mobile/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: 8661d8aecd626f7f57ccbcb735553edc05a2e713 8 | channel: stable 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /labellab_mobile/README.md: -------------------------------------------------------------------------------- 1 | # LabelLab Mobile App 2 | 3 | ### Mobile client for LabelLab, built using [Flutter](https://flutter.dev/) 4 | 5 |
6 | 7 |
8 | 9 | 10 | 11 |
12 | 13 |
14 | 15 | ## Guide 16 | 17 | - Please follow these [instructions](https://github.com/scorelab/LabelLab/wiki/Mobile-Development-Setup) to setup the mobile application on your local system or build an APK. 18 | 19 | - To learn more about the application, check out the [Mobile Wiki](https://github.com/scorelab/LabelLab/wiki/Mobile-Screenshots) 20 | -------------------------------------------------------------------------------- /labellab_mobile/android/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | android 4 | Project android created by Buildship. 5 | 6 | 7 | 8 | 9 | org.eclipse.buildship.core.gradleprojectbuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.buildship.core.gradleprojectnature 16 | 17 | 18 | -------------------------------------------------------------------------------- /labellab_mobile/android/.settings/org.eclipse.buildship.core.prefs: -------------------------------------------------------------------------------- 1 | connection.project.dir= 2 | eclipse.preferences.version=1 3 | -------------------------------------------------------------------------------- /labellab_mobile/android/app/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /labellab_mobile/android/app/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | app 4 | Project app created by Buildship. 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.buildship.core.gradleprojectbuilder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.jdt.core.javanature 21 | org.eclipse.buildship.core.gradleprojectnature 22 | 23 | 24 | -------------------------------------------------------------------------------- /labellab_mobile/android/app/.settings/org.eclipse.buildship.core.prefs: -------------------------------------------------------------------------------- 1 | connection.project.dir=.. 2 | eclipse.preferences.version=1 3 | -------------------------------------------------------------------------------- /labellab_mobile/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /labellab_mobile/android/app/src/main/kotlin/org/scorelab/labellab_mobile/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package org.scorelab.labellab_mobile 2 | 3 | 4 | import io.flutter.embedding.android.FlutterActivity 5 | 6 | 7 | class MainActivity: FlutterActivity() { 8 | } 9 | -------------------------------------------------------------------------------- /labellab_mobile/android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /labellab_mobile/android/app/src/main/res/drawable/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scorelab/LabelLab/080a7cc7fa5a32b042535b1e1214b60bf5881501/labellab_mobile/android/app/src/main/res/drawable/splash.png -------------------------------------------------------------------------------- /labellab_mobile/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scorelab/LabelLab/080a7cc7fa5a32b042535b1e1214b60bf5881501/labellab_mobile/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /labellab_mobile/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scorelab/LabelLab/080a7cc7fa5a32b042535b1e1214b60bf5881501/labellab_mobile/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /labellab_mobile/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scorelab/LabelLab/080a7cc7fa5a32b042535b1e1214b60bf5881501/labellab_mobile/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /labellab_mobile/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scorelab/LabelLab/080a7cc7fa5a32b042535b1e1214b60bf5881501/labellab_mobile/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /labellab_mobile/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scorelab/LabelLab/080a7cc7fa5a32b042535b1e1214b60bf5881501/labellab_mobile/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /labellab_mobile/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | -------------------------------------------------------------------------------- /labellab_mobile/android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /labellab_mobile/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlin_version = '1.6.10' 3 | repositories { 4 | google() 5 | jcenter() 6 | } 7 | 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:7.1.2' 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 11 | classpath 'com.google.gms:google-services:4.3.10' 12 | } 13 | } 14 | 15 | allprojects { 16 | repositories { 17 | google() 18 | jcenter() 19 | } 20 | } 21 | 22 | rootProject.buildDir = '../build' 23 | subprojects { 24 | project.buildDir = "${rootProject.buildDir}/${project.name}" 25 | } 26 | subprojects { 27 | project.evaluationDependsOn(':app') 28 | } 29 | 30 | task clean(type: Delete) { 31 | delete rootProject.buildDir 32 | } 33 | -------------------------------------------------------------------------------- /labellab_mobile/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.enableJetifier=true 3 | android.useAndroidX=true 4 | android.enableR8=true 5 | -------------------------------------------------------------------------------- /labellab_mobile/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Jun 23 08:50:38 CEST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https://services.gradle.org/distributions/gradle-7.4-all.zip 7 | -------------------------------------------------------------------------------- /labellab_mobile/android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() 4 | 5 | def plugins = new Properties() 6 | def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') 7 | if (pluginsFile.exists()) { 8 | pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } 9 | } 10 | 11 | plugins.each { name, path -> 12 | def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() 13 | include ":$name" 14 | project(":$name").projectDir = pluginDirectory 15 | } 16 | -------------------------------------------------------------------------------- /labellab_mobile/assets/images/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scorelab/LabelLab/080a7cc7fa5a32b042535b1e1214b60bf5881501/labellab_mobile/assets/images/splash.png -------------------------------------------------------------------------------- /labellab_mobile/ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 8.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /labellab_mobile/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /labellab_mobile/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /labellab_mobile/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /labellab_mobile/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /labellab_mobile/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /labellab_mobile/ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Flutter 3 | 4 | @UIApplicationMain 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /labellab_mobile/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scorelab/LabelLab/080a7cc7fa5a32b042535b1e1214b60bf5881501/labellab_mobile/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /labellab_mobile/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scorelab/LabelLab/080a7cc7fa5a32b042535b1e1214b60bf5881501/labellab_mobile/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /labellab_mobile/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scorelab/LabelLab/080a7cc7fa5a32b042535b1e1214b60bf5881501/labellab_mobile/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /labellab_mobile/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scorelab/LabelLab/080a7cc7fa5a32b042535b1e1214b60bf5881501/labellab_mobile/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /labellab_mobile/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scorelab/LabelLab/080a7cc7fa5a32b042535b1e1214b60bf5881501/labellab_mobile/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /labellab_mobile/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scorelab/LabelLab/080a7cc7fa5a32b042535b1e1214b60bf5881501/labellab_mobile/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /labellab_mobile/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scorelab/LabelLab/080a7cc7fa5a32b042535b1e1214b60bf5881501/labellab_mobile/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /labellab_mobile/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scorelab/LabelLab/080a7cc7fa5a32b042535b1e1214b60bf5881501/labellab_mobile/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /labellab_mobile/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scorelab/LabelLab/080a7cc7fa5a32b042535b1e1214b60bf5881501/labellab_mobile/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /labellab_mobile/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scorelab/LabelLab/080a7cc7fa5a32b042535b1e1214b60bf5881501/labellab_mobile/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /labellab_mobile/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scorelab/LabelLab/080a7cc7fa5a32b042535b1e1214b60bf5881501/labellab_mobile/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /labellab_mobile/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scorelab/LabelLab/080a7cc7fa5a32b042535b1e1214b60bf5881501/labellab_mobile/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /labellab_mobile/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scorelab/LabelLab/080a7cc7fa5a32b042535b1e1214b60bf5881501/labellab_mobile/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /labellab_mobile/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scorelab/LabelLab/080a7cc7fa5a32b042535b1e1214b60bf5881501/labellab_mobile/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /labellab_mobile/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scorelab/LabelLab/080a7cc7fa5a32b042535b1e1214b60bf5881501/labellab_mobile/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /labellab_mobile/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /labellab_mobile/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scorelab/LabelLab/080a7cc7fa5a32b042535b1e1214b60bf5881501/labellab_mobile/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /labellab_mobile/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scorelab/LabelLab/080a7cc7fa5a32b042535b1e1214b60bf5881501/labellab_mobile/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /labellab_mobile/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scorelab/LabelLab/080a7cc7fa5a32b042535b1e1214b60bf5881501/labellab_mobile/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /labellab_mobile/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /labellab_mobile/ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" -------------------------------------------------------------------------------- /labellab_mobile/lib/data/interceptor/token_interceptor.dart: -------------------------------------------------------------------------------- 1 | import 'package:dio/dio.dart'; 2 | import 'package:labellab_mobile/data/repository.dart'; 3 | 4 | class RetryOnAuthFailInterceptor extends Interceptor { 5 | Dio? _dio; 6 | RetryOnAuthFailInterceptor(this._dio); 7 | 8 | @override 9 | Future onError(DioError err, ErrorInterceptorHandler handler) async { 10 | if (err.response != null && err.response!.statusCode == 401) { 11 | _dio!.interceptors.requestLock.lock(); 12 | _dio!.interceptors.responseLock.lock(); 13 | 14 | Repository().refreshToken(); 15 | 16 | _dio!.interceptors.requestLock.unlock(); 17 | _dio!.interceptors.responseLock.unlock(); 18 | 19 | return handler.resolve(err.response!); 20 | } 21 | 22 | return handler.next(err); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /labellab_mobile/lib/data/local/entities/classification_entity.dart: -------------------------------------------------------------------------------- 1 | import 'package:labellab_mobile/model/classification.dart'; 2 | 3 | class ClassificationEntity extends Classification { 4 | static const String table = 'classification'; 5 | static const String columnId = '_id'; 6 | static const String columnImageURL = 'image_url'; 7 | 8 | ClassificationEntity.from(Classification classification) { 9 | this.id = classification.id; 10 | this.imageUrl = classification.imageUrl; 11 | } 12 | 13 | ClassificationEntity.fromMap(Map map) { 14 | id = map[columnId]; 15 | imageUrl = map[columnImageURL]; 16 | } 17 | 18 | Map toMap() { 19 | var map = { 20 | "image_url": imageUrl, 21 | }; 22 | if (id != null) { 23 | map[columnId] = id; 24 | } 25 | return map; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /labellab_mobile/lib/data/local/entities/issue_entity.dart: -------------------------------------------------------------------------------- 1 | import 'package:labellab_mobile/model/issue.dart'; 2 | 3 | class IssueEntity extends Issue { 4 | static const String table = 'issue'; 5 | static const String columnId = '_id'; 6 | static const String columnName = 'issue_title'; 7 | static const String columnDescription = 'description'; 8 | 9 | IssueEntity.from(Issue issue) { 10 | this.id = issue.id; 11 | this.issueTitle = issue.issueTitle; 12 | this.description = issue.description; 13 | } 14 | 15 | IssueEntity.fromMap(Map map) { 16 | id = map[columnId]; 17 | issueTitle = map[columnName]; 18 | description = map[columnDescription]; 19 | } 20 | 21 | Map toMap() { 22 | var map = {columnName: issueTitle}; 23 | if (id != null) { 24 | map[columnId] = id; 25 | } 26 | if (description != null) { 27 | map[columnDescription] = description; 28 | } 29 | return map; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /labellab_mobile/lib/data/local/entities/project_entity.dart: -------------------------------------------------------------------------------- 1 | import 'package:labellab_mobile/model/project.dart'; 2 | 3 | class ProjectEntity extends Project { 4 | static const String table = 'project'; 5 | static const String columnId = '_id'; 6 | static const String columnName = 'name'; 7 | static const String columnDescription = 'description'; 8 | 9 | ProjectEntity.from(Project project) { 10 | this.id = project.id; 11 | this.name = project.name; 12 | this.description = project.description; 13 | } 14 | 15 | ProjectEntity.fromMap(Map map) { 16 | id = map[columnId]; 17 | name = map[columnName]; 18 | description = map[columnDescription]; 19 | } 20 | 21 | Map toMap() { 22 | var map = {columnName: name}; 23 | if (id != null) { 24 | map[columnId] = id; 25 | } 26 | if (description != null) { 27 | map[columnDescription] = description; 28 | } 29 | return map; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /labellab_mobile/lib/data/local/issue_provider.dart: -------------------------------------------------------------------------------- 1 | import 'package:labellab_mobile/model/issue.dart'; 2 | import 'package:sqflite/sqflite.dart'; 3 | 4 | import 'entities/issue_entity.dart'; 5 | 6 | class IssueProvider { 7 | static const String _path = "labellab/issue"; 8 | 9 | late Database db; 10 | 11 | Future open() async { 12 | db = await openDatabase(_path, version: 1, 13 | onCreate: (Database db, int version) async { 14 | await db.execute(''' 15 | create table ${IssueEntity.table} ( 16 | ${IssueEntity.columnId} text primary key, 17 | ${IssueEntity.columnDescription} text, 18 | ${IssueEntity.columnName} text not null) 19 | '''); 20 | }); 21 | } 22 | 23 | 24 | Future?> getIssues() async { 25 | List maps = await db.query(IssueEntity.table, 26 | columns: [IssueEntity.columnId, IssueEntity.columnName]); 27 | if (maps.length > 0) { 28 | return maps.map((item) => IssueEntity.fromMap(item as Map)).toList(); 29 | } 30 | return null; 31 | } 32 | 33 | Future close() async => db.close(); 34 | } 35 | -------------------------------------------------------------------------------- /labellab_mobile/lib/data/local/user_provider.dart: -------------------------------------------------------------------------------- 1 | import 'package:labellab_mobile/model/user.dart'; 2 | import 'package:shared_preferences/shared_preferences.dart'; 3 | 4 | class UserProvider { 5 | Future insert(User user) { 6 | return SharedPreferences.getInstance().then((pref) { 7 | pref.setString("id", user.id!); 8 | pref.setString("name", user.name!); 9 | pref.setString("username", user.username!); 10 | pref.setString("email", user.email!); 11 | }); 12 | } 13 | 14 | Future getUser() { 15 | return SharedPreferences.getInstance().then((pref) { 16 | User user = User(); 17 | user.id = pref.getString("id"); 18 | user.name = pref.getString("name"); 19 | user.username = pref.getString("username"); 20 | user.email = pref.getString("email"); 21 | if (user.id == null) return null; 22 | return user; 23 | }); 24 | } 25 | 26 | Future delete() { 27 | return SharedPreferences.getInstance().then((pref) { 28 | pref.remove("id"); 29 | pref.remove("name"); 30 | pref.remove("username"); 31 | pref.remove("email"); 32 | }); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /labellab_mobile/lib/data/remote/dto/api_response.dart: -------------------------------------------------------------------------------- 1 | class ApiResponse { 2 | bool? success; 3 | String? msg; 4 | 5 | ApiResponse(dynamic json) { 6 | this.success = json['success']; 7 | this.msg = json['msg']; 8 | } 9 | 10 | ApiResponse.error(error) { 11 | this.success = false; 12 | this.msg = error; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /labellab_mobile/lib/data/remote/dto/google_user_request.dart: -------------------------------------------------------------------------------- 1 | import 'package:google_sign_in/google_sign_in.dart'; 2 | 3 | class GoogleUserRequest { 4 | String? id; 5 | String? displayName; 6 | String? photoUrl; 7 | String? email; 8 | String? accessToken; 9 | 10 | GoogleUserRequest(GoogleSignInAccount user, this.accessToken) { 11 | this.id = user.id; 12 | this.displayName = user.displayName; 13 | this.photoUrl = user.photoUrl; 14 | this.email = user.email; 15 | } 16 | 17 | Map toMap() { 18 | return { 19 | "id": id, 20 | "displayName": displayName, 21 | "photoUrl": photoUrl, 22 | "email": email, 23 | "accessToken": accessToken 24 | }; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /labellab_mobile/lib/data/remote/dto/login_response.dart: -------------------------------------------------------------------------------- 1 | class LoginResponse { 2 | bool? success; 3 | String? accessToken; 4 | String? refreshToken; 5 | String? msg; 6 | 7 | LoginResponse(dynamic json) { 8 | this.success = json['success']; 9 | this.accessToken = json['access_token']; 10 | this.refreshToken = json['refresh_token']; 11 | this.msg = json['msg']; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /labellab_mobile/lib/data/remote/dto/refresh_response.dart: -------------------------------------------------------------------------------- 1 | class RefreshResponse { 2 | String? accessToken; 3 | String? message; 4 | 5 | RefreshResponse(dynamic json) { 6 | this.accessToken = json['access_token']; 7 | this.message = json['msg']; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /labellab_mobile/lib/data/remote/dto/register_response.dart: -------------------------------------------------------------------------------- 1 | class RegisterResponse { 2 | String? msg; 3 | String? errField; 4 | 5 | RegisterResponse(dynamic json) { 6 | this.msg = json['msg']; 7 | this.errField = json['err_field']; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /labellab_mobile/lib/data/remote/dto/time_value.dart: -------------------------------------------------------------------------------- 1 | class TimeValue { 2 | final DateTime stamp; 3 | final int value; 4 | 5 | TimeValue(this.stamp, this.value); 6 | } 7 | -------------------------------------------------------------------------------- /labellab_mobile/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:labellab_mobile/labellab_app.dart'; 3 | 4 | void main() => runApp(LabelLabApp()); -------------------------------------------------------------------------------- /labellab_mobile/lib/model/auth_user.dart: -------------------------------------------------------------------------------- 1 | class AuthUser { 2 | String? email; 3 | String? password; 4 | 5 | AuthUser(this.email, this.password); 6 | 7 | AuthUser.just(); 8 | 9 | Map toMap() { 10 | return { 11 | "email": email, 12 | "password": password 13 | }; 14 | } 15 | } -------------------------------------------------------------------------------- /labellab_mobile/lib/model/classification.dart: -------------------------------------------------------------------------------- 1 | import 'package:labellab_mobile/model/classification_label.dart'; 2 | 3 | class Classification { 4 | String? id; 5 | String? imageName; 6 | String? imageUrl; 7 | List? labels; 8 | DateTime? createdAt; 9 | 10 | Classification(); 11 | 12 | Classification.fromJson(dynamic json, {String? staticEndpoint}) { 13 | id = json["id"].toString(); 14 | imageName = json["image_name"]; 15 | imageUrl = (staticEndpoint != null ? staticEndpoint : "") + 16 | json["user_id"].toString() + 17 | "/" + 18 | json["image_url"]; 19 | createdAt = DateTime.parse(json["classified_at"]); 20 | labels = [ 21 | ClassificationLabel.fromValues( 22 | name: json["label"], confidence: json["confidence"]) 23 | ].toList(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /labellab_mobile/lib/model/classification_label.dart: -------------------------------------------------------------------------------- 1 | class ClassificationLabel { 2 | String? id; 3 | String? name; 4 | double? confidence; 5 | 6 | ClassificationLabel(); 7 | 8 | ClassificationLabel.fromJson(dynamic json) { 9 | id = json["_id"]; 10 | name = json["label_name"]; 11 | confidence = json["confidence"] ?? 0; 12 | } 13 | 14 | ClassificationLabel.fromValues({this.name, this.confidence}); 15 | } 16 | -------------------------------------------------------------------------------- /labellab_mobile/lib/model/comment.dart: -------------------------------------------------------------------------------- 1 | class Comment { 2 | int? id; 3 | String? body; 4 | int? issueId; 5 | int? userId; 6 | String? timestamp; 7 | String? thumbnail; 8 | String? username; 9 | 10 | Comment( 11 | {this.body, 12 | this.id, 13 | this.issueId, 14 | this.thumbnail, 15 | this.timestamp, 16 | this.userId, 17 | this.username}); 18 | 19 | Comment.fromJson(dynamic json, {bool isDense = false}) { 20 | id = json['id']; 21 | body = json['body']; 22 | issueId = json['issue_id']; 23 | thumbnail = json['thumbnail']; 24 | timestamp = json['timestamp']; 25 | userId = json['user_id']; 26 | username = json['username']; 27 | 28 | } 29 | 30 | Map toMap() { 31 | return { 32 | "body": body, 33 | }; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /labellab_mobile/lib/model/group.dart: -------------------------------------------------------------------------------- 1 | import 'package:labellab_mobile/model/image.dart'; 2 | 3 | class Group { 4 | String? id; 5 | String? name; 6 | String? projectId; 7 | List? images; 8 | 9 | Group({this.id, this.name, this.projectId, this.images}); 10 | 11 | Group.fromJson(dynamic json) { 12 | id = json["_id"]; 13 | name = json["groupName"]; 14 | projectId = json["projectId"]; 15 | images = 16 | (json["images"] as List).map((image) => Image.fromJson(image)).toList(); 17 | } 18 | 19 | Map toMap() { 20 | return { 21 | "groupName": name, 22 | "projectId": projectId, 23 | }; 24 | } 25 | 26 | // Creates a mock group for testing 27 | Group.mock(this.projectId, this.images) { 28 | id = "thisisarandomid"; 29 | name = "Test group 1"; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /labellab_mobile/lib/model/image.dart: -------------------------------------------------------------------------------- 1 | import 'package:labellab_mobile/model/label_selection.dart'; 2 | import 'package:logger/logger.dart'; 3 | 4 | class Image { 5 | String? id; 6 | String? imageUrl; 7 | String? name; 8 | double? width; 9 | double? height; 10 | List? labels; 11 | bool? isLabeled; 12 | 13 | Image({this.imageUrl, this.labels}); 14 | 15 | Image.fromJson(dynamic json, {String? imageEndpoint}) { 16 | id = json["id"].toString(); 17 | name = json['image_name']; 18 | imageUrl = (imageEndpoint != null ? imageEndpoint : "") + 19 | json['project_id'].toString() + 20 | "/" + 21 | json["image_url"]; 22 | width = double.parse(json["width"].toString()); 23 | height = double.parse(json["height"].toString()); 24 | isLabeled = json['labelled']; 25 | if (json["labelData"] != null) 26 | labels = (json["labelData"] as List) 27 | .map((label) => LabelSelection.fromJson(label)) 28 | .toList(); 29 | 30 | Logger().i(name); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /labellab_mobile/lib/model/label.dart: -------------------------------------------------------------------------------- 1 | enum LabelType { RECTANGLE, POLYGON } 2 | 3 | class Label { 4 | String? id; 5 | String? name; 6 | LabelType? type; 7 | String? projectId; 8 | String? count; 9 | DateTime? createdAt; 10 | late List imageIds; 11 | 12 | Label({this.id, this.name, this.type}); 13 | 14 | Label.fromJson(dynamic json) { 15 | id = json["id"].toString(); 16 | name = json["label_name"]; 17 | type = 18 | json["label_type"] == "bbox" ? LabelType.RECTANGLE : LabelType.POLYGON; 19 | projectId = json['project_id'].toString(); 20 | count = json['count'].toString(); 21 | imageIds = json['labeldata'] != null && json["labeldata"]["id"] != null 22 | ? (json['labeldata']['id'] as List) 23 | .map((item) => item['image_id'].toString()) 24 | .toList() 25 | : []; 26 | // createdAt = DateTime.parse(json['created_at']); 27 | } 28 | 29 | Map toMap() { 30 | return { 31 | "label_name": name, 32 | "label_type": type == LabelType.RECTANGLE ? "bbox" : "polygon", 33 | }; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /labellab_mobile/lib/model/location.dart: -------------------------------------------------------------------------------- 1 | class Location { 2 | String? name; 3 | double? latitude; 4 | double? longitude; 5 | 6 | Location({this.name = "", this.latitude, this.longitude}); 7 | 8 | Location.fromJson(dynamic json) { 9 | name = json['name']; 10 | latitude = double.parse(json['latitude'].toString()); 11 | longitude = double.parse(json['longitude'].toString()); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /labellab_mobile/lib/model/member.dart: -------------------------------------------------------------------------------- 1 | class Member { 2 | String? id, name, email, role, teamId, teamName, projectId; 3 | 4 | Member( 5 | {this.id, 6 | this.name, 7 | this.email, 8 | this.role, 9 | this.teamId, 10 | this.teamName, 11 | this.projectId}); 12 | 13 | Member.fromJson(dynamic json) { 14 | id = json['user_id'].toString(); 15 | name = json['name']; 16 | email = json['email']; 17 | teamId = json['team_id'].toString(); 18 | teamName = json['team_name']; 19 | role = json['team_role']; 20 | projectId = json['project_id'].toString(); 21 | } 22 | 23 | bool operator ==(Object other) => 24 | identical(this, other) || (other as Member).email == email; 25 | 26 | int get hashCode => id.hashCode; 27 | } 28 | -------------------------------------------------------------------------------- /labellab_mobile/lib/model/message.dart: -------------------------------------------------------------------------------- 1 | class Message { 2 | String? id; 3 | String? body; 4 | String? teamId; 5 | String? userId; 6 | String? username; 7 | String? timestamp; 8 | 9 | Message.fromJson(Map json) { 10 | id = json['id'].toString(); 11 | body = json['body']; 12 | teamId = json['team_id'].toString(); 13 | userId = json['user_id'].toString(); 14 | username = json['username']; 15 | timestamp = json['timestamp']; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /labellab_mobile/lib/model/register_user.dart: -------------------------------------------------------------------------------- 1 | import 'package:labellab_mobile/model/auth_user.dart'; 2 | 3 | class RegisterUser extends AuthUser { 4 | String? name; 5 | String? username; 6 | String? password2; 7 | 8 | RegisterUser(this.name, this.username, email, password, this.password2) 9 | : super(email, password); 10 | 11 | RegisterUser.just() : super.just(); 12 | 13 | Map toMap() { 14 | return { 15 | "name": name, 16 | "username": username, 17 | "email": email, 18 | "password": password, 19 | "password2": password2, 20 | }; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /labellab_mobile/lib/model/team_member.dart: -------------------------------------------------------------------------------- 1 | class TeamMember { 2 | String? id; 3 | String? name; 4 | String? email; 5 | String? username; 6 | 7 | TeamMember.fromJson(dynamic json) { 8 | id = json['id'].toString(); 9 | name = json['name']; 10 | email = json['email']; 11 | username = json['username']; 12 | } 13 | 14 | TeamMember.fromSparseJson(dynamic json) { 15 | id = json['user_id'].toString(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /labellab_mobile/lib/model/upload_image.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | 3 | import 'package:labellab_mobile/model/label.dart'; 4 | import 'package:multi_image_picker/multi_image_picker.dart'; 5 | 6 | class UploadImageState { 7 | static const PENDING = 0; 8 | static const LOADING = 1; 9 | static const SUCCESS = 2; 10 | static const ERROR = 3; 11 | } 12 | 13 | class UploadImage { 14 | int? state; 15 | File? image; 16 | String? name; 17 | List