diff --git a/LICENSE.md b/LICENSE.md index 65c5ca88a6..33cfb3defb 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -60,7 +60,7 @@ version: b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. - 3. Object Code Incorporating Material from Library Header Files. + 3. Object Code Incorporating Material from Library Header GoToIcon. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object diff --git a/lib/Controller/API/V3/QualityReportControllerAPI.php b/lib/Controller/API/V3/QualityReportControllerAPI.php index eda80badb7..6c21ea2ede 100644 --- a/lib/Controller/API/V3/QualityReportControllerAPI.php +++ b/lib/Controller/API/V3/QualityReportControllerAPI.php @@ -189,6 +189,7 @@ private function _formatSegments(array $segments, array $ttlArray, array $filesI $seg['ice_modified'] = $segment->ice_modified; $seg['is_pre_translated'] = $segment->is_pre_translated; $seg['issues'] = $segment->issues; + $seg['history'] = $segment->history; $seg['last_revisions'] = $segment->last_revisions; $seg['last_translation'] = $segment->last_translation; $seg['locked'] = $segment->locked; diff --git a/lib/Model/QualityReport/HistoryElementStruct.php b/lib/Model/QualityReport/HistoryElementStruct.php new file mode 100644 index 0000000000..eb887570a4 --- /dev/null +++ b/lib/Model/QualityReport/HistoryElementStruct.php @@ -0,0 +1,23 @@ +findByIdModelAndIdParent( - $this->chunk->getProject()->id_qa_model, - $options['filter']['issue_category'] - ); - - if (!empty($subCategories) > 0) { - $options['filter']['issue_category'] = array_map(function (CategoryStruct $subcat) { - return $subcat->id; - }, $subCategories); - } + if (isset($options['filter']['issue_category'])) { + $options['filter']['issue_category'] = $this->issueCategoryIds($options['filter']['issue_category']); } /** @@ -90,6 +81,39 @@ public function getSegmentsIdForQR($step, int $ref_segment, $where = "after", $o return $segments_id; } + /** + * Processes a string of issue category IDs, converting them into an array of integers, + * and expands the list by including IDs of subcategories if applicable. + * + * @param string $issue_category A comma-separated string of issue category IDs. + * If it contains 'all', the method returns null. + * + * @return array|null Returns an array of category IDs, including subcategory IDs, or null if 'all' is present. + */ + private function issueCategoryIds(string $issue_category): ?array + { + if (str_contains($issue_category, 'all')){ + return null; + } + + $issue_category = array_map('intval', explode(',', $issue_category)); + + foreach ($issue_category as $issue_category_id) { + $subCategories = (new CategoryDao())->findByIdModelAndIdParent( + $this->chunk->getProject()->id_qa_model, + $issue_category_id + ); + + if (!empty($subCategories)) { + foreach ($subCategories as $subcat) { + $issue_category[] = (int)$subcat->id; + } + } + } + + return $issue_category; + } + /** * @param QualityReportSegmentStruct $seg * @param MateCatFilter $Filter @@ -180,10 +204,9 @@ public function getSegmentsForQR(array $segment_ids, $isForUI = false) $commentsDao = new CommentDao; $comments = $commentsDao->getThreadsBySegments($segment_ids, $this->chunk->id); - $all_events = []; - $translationVersionDao = new TranslationVersionDao; $all_events = $translationVersionDao->getAllRelevantEvents($segment_ids, $this->chunk->id); + $history_events = $translationVersionDao->historyEvents($segment_ids, $this->chunk->id); $segments = []; @@ -205,7 +228,8 @@ public function getSegmentsForQR(array $segment_ids, $isForUI = false) $this->_commonSegmentAssignments($seg, $Filter, $featureSet, $this->chunk, $isForUI); $this->_assignIssues($seg, $issues ?? [], $issue_comments); $this->_assignComments($seg, $comments); - $this->_populateLastTranslationAndRevision($seg, $Filter, $all_events, $isForUI); + $this->_populateLastTranslationAndRevision($seg, $Filter, $all_events, $isForUI); + $this->_populateHistory($seg, $Filter, $history_events,$issues ?? [], $isForUI); $seg->pee_translation_revise = $seg->getPEEBwtTranslationRevise(); $seg->pee_translation_suggestion = $seg->getPEEBwtTranslationSuggestion(); @@ -216,6 +240,55 @@ public function getSegmentsForQR(array $segment_ids, $isForUI = false) return $segments; } + /** + * Populates the history for a given quality report segment by organizing events and associated issues. + * + * @param QualityReportSegmentStruct $seg The segment structure where the history will be populated. + * @param MateCatFilter $Filter The filter used to process translations for UI rendering. + * @param array $events An array of SegmentEventsStruct objects representing the events related to the segment. + * @param array $issues An array of issue objects to associate with the events, filtered by segment and version. + * @param bool $isForUI Indicates whether the translation should be processed for UI display purposes. + * + * @return void + */ + protected function _populateHistory( + QualityReportSegmentStruct $seg, + MateCatFilter $Filter, + array $events = [], + array $issues = [], + bool $isForUI = false + ) + { + $elements = []; + + $eventsForThisSegment = array_filter($events, function (HistoryElementStruct $event) use ($seg) { + return $event->id_segment == $seg->sid; + }); + + /** @var HistoryElementStruct $event */ + foreach ($eventsForThisSegment as $event) { + $translation = ($isForUI) ? $Filter->fromLayer0ToLayer2($event->translation) : $event->translation; + + $elements[] = [ + 'status' => $event->status, + 'date' => $event->creation_date ?? $event->create_date, + 'revision_number' => ReviewUtils::sourcePageToRevisionNumber($event->source_page), + 'source_page' => $event->source_page, + 'version_number' => $event->version_number, + 'translation' => $translation, + 'issues' => array_filter($issues, function ($issue) use ($event) { + return + $issue->deleted_at === null && + $event->id_segment == $issue->segment_id && + $event->version_number == $issue->translation_version + ; + }) + ]; + } + + $seg->history = $elements; + } + /** * @return ChunkReviewStruct[] */ diff --git a/lib/Model/QualityReport/QualityReportSegmentStruct.php b/lib/Model/QualityReport/QualityReportSegmentStruct.php index 10ef9198d0..dc8b14743b 100644 --- a/lib/Model/QualityReport/QualityReportSegmentStruct.php +++ b/lib/Model/QualityReport/QualityReportSegmentStruct.php @@ -95,6 +95,8 @@ class QualityReportSegmentStruct extends AbstractDaoObjectStruct implements IDao protected string $tm_analysis_status; + public array $history = []; + /** * @return string */ diff --git a/lib/Model/QualityReport/SegmentEventsStruct.php b/lib/Model/QualityReport/SegmentEventsStruct.php index 5efddfbee0..896c6bbca7 100644 --- a/lib/Model/QualityReport/SegmentEventsStruct.php +++ b/lib/Model/QualityReport/SegmentEventsStruct.php @@ -20,7 +20,6 @@ */ class SegmentEventsStruct extends AbstractDaoObjectStruct implements IDaoStruct { - /** * @var int */ @@ -37,5 +36,4 @@ class SegmentEventsStruct extends AbstractDaoObjectStruct implements IDaoStruct * @var int */ protected int $source_page; - } \ No newline at end of file diff --git a/lib/Plugins/Features/TranslationVersions/Model/TranslationVersionDao.php b/lib/Plugins/Features/TranslationVersions/Model/TranslationVersionDao.php index 559205a892..35dd9fd9b2 100644 --- a/lib/Plugins/Features/TranslationVersions/Model/TranslationVersionDao.php +++ b/lib/Plugins/Features/TranslationVersions/Model/TranslationVersionDao.php @@ -6,6 +6,7 @@ use Model\DataAccess\Database; use Model\DataAccess\ShapelessConcreteStruct; use Model\Jobs\JobStruct; +use Model\QualityReport\HistoryElementStruct; use Model\QualityReport\SegmentEventsStruct; use Model\Translations\SegmentTranslationStruct; use PDO; @@ -249,6 +250,56 @@ public function getVersionsForRevision($id_job, $id_segment) ); } + /** + * @param $id_job + * @param $id_segment + * + * @return TranslationVersionStruct[] + */ + public function getVersionsForTranslationBySegment($id_job, $id_segment) + { + $sql = "SELECT * FROM segment_translation_versions " . + " WHERE id_job = :id_job AND id_segment = :id_segment " . + " ORDER BY creation_date DESC "; + } + public function historyEvents(array $segments_id, int $job_id) + { + $db = Database::obtain()->getConnection(); + + $prepare_str_segments_id = implode(', ', array_fill(0, count($segments_id), '?')); + + $query = "SELECT + id_segment, + first_sv.version_number, + null as source_page, + null as status, + null as create_date, + first_sv.creation_date, + first_sv.translation + FROM segment_translation_versions first_sv WHERE id_segment IN ( $prepare_str_segments_id ) AND id_job = ? AND version_number = 0 + UNION + SELECT ste.id_segment, ste.version_number, ste.source_page, ste.status, ste.create_date, stv.creation_date, stv.translation FROM segment_translation_events ste + INNER JOIN ( + SELECT creation_date, id_segment, translation, version_number, id_job + FROM segment_translation_versions + WHERE id_segment IN ( $prepare_str_segments_id ) + AND id_job = ? + UNION + SELECT null as creation_date, id_segment, translation, version_number, id_job + FROM segment_translations + WHERE id_segment IN ( $prepare_str_segments_id ) + AND id_job = ? + ) AS stv ON stv.version_number = ste.version_number AND stv.id_segment = ste.id_segment + + WHERE ste.id_segment IN ( $prepare_str_segments_id ) GROUP BY version_number, source_page;"; + + $stmt = $db->prepare($query); + $stmt->setFetchMode(PDO::FETCH_CLASS, HistoryElementStruct::class); + $stmt->execute(array_merge($segments_id, [$job_id], $segments_id, [$job_id], $segments_id, [$job_id], $segments_id)); + + return $stmt->fetchAll(); + } + /** * @param array $segments_id * @param int $job_id @@ -279,7 +330,7 @@ public function getAllRelevantEvents(array $segments_id, int $job_id): array AND id_job = ? ) AS stv JOIN ( - SELECT MAX(version_number) AS version_number, ste.id_segment, ste.source_page + SELECT MAX(version_number) AS version_number, ste.id, ste.id_segment, ste.source_page FROM segment_translation_events ste WHERE id_segment IN ( $prepare_str_segments_id ) AND ste.id_job = ? diff --git a/lib/View/templates/_manage.html b/lib/View/templates/_manage.html index e72fcd4698..d9f60fc661 100755 --- a/lib/View/templates/_manage.html +++ b/lib/View/templates/_manage.html @@ -39,9 +39,7 @@
-
-
Loading Projects
-
+
diff --git a/public/css/sass/activity-log-main.scss b/public/css/sass/activity-log-main.scss index 85928eb2dd..dcb1f38e0f 100644 --- a/public/css/sass/activity-log-main.scss +++ b/public/css/sass/activity-log-main.scss @@ -18,7 +18,7 @@ .activity-log-table { height: 100%; overflow-y: auto; - border: 1px solid colors.$grey8; + border: 1px solid colors.$grey200; .activity-log-table-columns-name, .activity-log-table-columns-content { @@ -47,7 +47,7 @@ .activity-log-table-columns-content { > * { height: 40px; - border: 1px solid colors.$grey8; + border: 1px solid colors.$grey200; border-top: unset; padding: 10px; border-left: unset; @@ -58,13 +58,13 @@ } &:nth-child(odd) { - background-color: colors.$grey5; + background-color: colors.$grey50; } } .activity-table-column-order { - background-color: colors.$grey9; - border: 1px solid colors.$grey8; + background-color: colors.$grey75; + border: 1px solid colors.$grey200; padding: 5px; justify-content: space-between; cursor: pointer; @@ -97,7 +97,7 @@ width: 160px; label { - color: colors.$grey6; + color: colors.$grey700; } .select { @@ -105,7 +105,7 @@ padding: 5px; &:hover { - border-color: rgba(colors.$grey8, 0.8); + border-color: rgba(colors.$grey200, 0.8); box-shadow: none; } } @@ -115,7 +115,7 @@ width: 250px; font-size: 14px; border-radius: 2px; - border: 1px solid colors.$grey2; + border: 1px solid colors.$grey300; padding: 7px; } } diff --git a/public/css/sass/cattool.scss b/public/css/sass/cattool.scss index e76e856e15..fa40ea597b 100644 --- a/public/css/sass/cattool.scss +++ b/public/css/sass/cattool.scss @@ -1,5 +1,6 @@ @use 'commons/mixins'; @use 'commons/_colors'; +@use 'commons/variables'; @use 'components/segment/IcuHighlight'; body.cattool { //display: flex; @@ -7,7 +8,7 @@ body.cattool { //flex-direction: column; overflow-y: hidden !important; padding: unset; - background-color: colors.$grey5; + background-color: colors.$grey50; .page-content { display: flex; @@ -49,7 +50,7 @@ body.cattool { .pointer-first-segment { height: 36px; width: 36px; - background: colors.$darkBlue url('/public/img/icons/arrow-up.svg') no-repeat + background: colors.$blue900 url('/public/img/icons/arrow-up.svg') no-repeat center center; background-size: 24px; border-radius: 50%; @@ -60,7 +61,7 @@ body.cattool { bottom: 8px; cursor: pointer; &:hover { - background-color: colors.$darkBlueHover; + background-color: colors.$blue950; } } } @@ -84,8 +85,8 @@ body.cattool { height: 24px; } .icon-warning-sign.qa-icon { - background-color: colors.$red800; - color: #fff; + background-color: colors.$red400; + color: colors.$white; display: flex; padding: 3px; justify-content: center; @@ -93,7 +94,7 @@ body.cattool { gap: 6px; align-self: stretch; cursor: pointer; - border-radius: 8px; + border-radius: variables.$border-radius-default; width: 18px; height: 18px; margin-left: 8px; @@ -114,7 +115,7 @@ body.cattool { line-height: 12px; &.badge-red { color: colors.$white; - background-color: colors.$red800; + background-color: colors.$red400; } &.badge-orange { color: colors.$black; @@ -122,7 +123,7 @@ body.cattool { } &.badge-blue { color: colors.$white; - background-color: colors.$blue800; + background-color: colors.$blue400; } } } @@ -140,33 +141,37 @@ body.cattool { } } -.segment-target-toolbar { +.segment-actions-container { display: flex; + justify-content: end; + flex-wrap: wrap; gap: 8px; - margin-left: -11px; margin-top: 8px; } -.segment-target-toolbar-icon { - width: 32px !important; - height: 32px !important; - padding: 0 !important; +.segment-target-toolbar { + display: flex; + gap: 8px; + flex-grow: 1; + margin-left: -11px; - &:disabled { - color: colors.$grey8 !important; - box-shadow: inset 0 0 0 1px colors.$grey8 !important; + .last-ai-feature-button:not(:last-child) { + margin-right: 15px; - svg { - color: colors.$grey8 !important; + &::after { + position: absolute; + content: ''; + left: 43px; + width: 1px; + height: 100%; + background-color: colors.$grey150; } } } -.segment-target-toolbar-dropdown-trigger { - height: 32px !important; - padding: 0 16px !important; - font-weight: bold; - font-size: 14px !important; +.segment-target-toolbar-icon-bundled { + padding: 0 !important; + font-weight: normal !important; } .lara-styles-dropdown { @@ -174,7 +179,7 @@ body.cattool { .lara-styles-dropdown-item { font-size: 14px; - color: colors.$grey7; + color: colors.$grey400; padding: 12px; border-radius: 6px; text-wrap: auto; @@ -187,10 +192,10 @@ body.cattool { &.lara-styles-dropdown-item-active, &:hover { - background-color: rgba(#0588f9, 0.16); - color: #0099cc; + background-color: rgba(colors.$blue400, 0.16); + color: colors.$blue500; > span { - color: #017cac; + color: colors.$blue600; } } } diff --git a/public/css/sass/common-components.scss b/public/css/sass/common-components.scss index a4a8d20858..c1f69db376 100644 --- a/public/css/sass/common-components.scss +++ b/public/css/sass/common-components.scss @@ -2,7 +2,6 @@ @use 'components/common/Dropdown'; @use 'components/common/CookieConsent'; @use 'components/common/Switch'; -@use 'components/common/MenuButton'; @use 'components/common/Tooltip'; @use 'components/common/Button'; @use 'components/common/Popover'; @@ -20,3 +19,4 @@ @use 'components/common/OnBoardingTooltip'; @use 'components/common/ProgressBar'; @use 'components/common/Badge'; +@use 'components/common/SpinnerLoader'; diff --git a/public/css/sass/common-main.scss b/public/css/sass/common-main.scss index deb89f410e..cbdf6291a6 100644 --- a/public/css/sass/common-main.scss +++ b/public/css/sass/common-main.scss @@ -1,5 +1,6 @@ @use 'commons/variables'; @use 'commons/colors'; +@use 'commons/layout'; @use 'vendor_mc/semantic/matecat_semantic'; @use "commons/typography"; diff --git a/public/css/sass/common-modals.scss b/public/css/sass/common-modals.scss index fc5006d5e5..768869ca64 100644 --- a/public/css/sass/common-modals.scss +++ b/public/css/sass/common-modals.scss @@ -3,28 +3,6 @@ @use 'modals/PreferenceModal'; @use 'commons/colors'; -h1, -h2, -h3, -h4, -h5, -h6 { - font-family: 'Calibri', 'Helvetica Neue', Arial, Helvetica, sans-serif; -} - -h2 { - font-size: 22px; -} - -a { - font-family: 'Calibri', 'Helvetica Neue', Arial, Helvetica, sans-serif; -} - -::-webkit-input-placeholder { - /* Chrome/Opera/Safari */ - font-family: 'Calibri', 'Helvetica Neue', Arial, Helvetica, sans-serif; -} - /***********************/ /***** Login Footer ****/ @@ -34,11 +12,11 @@ a { text-decoration: underline; float: left; cursor: pointer; - color: colors.$linkBlue; + color: colors.$blue700; &:hover { text-decoration: none; - color: colors.$linkBlueHover; + color: colors.$blue400; } } @@ -69,7 +47,7 @@ a { .forgot-password { cursor: pointer; text-decoration: underline; - color: colors.$linkBlue; + color: colors.$blue700; } .dqf-modal input[type='text'], @@ -77,34 +55,32 @@ a { .login-container-left input, .register-form-container input[type='text'], .register-form-container input[type='password'], -.forgot-password-modal input, -.reset-password-modal input, .user-info-form input { margin-top: 5px; font-size: 14px; width: 100%; padding: 0.7em 0.6em; display: inline-block; - border: 1px solid #ccc; - box-shadow: inset 0 1px 3px #ddd; + border: 1px solid colors.$grey200; + box-shadow: inset 0 1px 3px colors.$grey200; border-radius: 4px; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; font-size: 15px; - color: #333; + color: colors.$grey1300; } .dqf-modal input[disabled] { - color: #999; + color: colors.$grey400; cursor: not-allowed; - background: colors.$grey2; + background: colors.$grey300; } .user-info-form input { margin-top: 5px; width: 100%; - color: #000; + color: colors.$black; } .login-button, @@ -125,35 +101,10 @@ a { width: 245px; } -.forgot-password-modal, -.reset-password-modal { - width: 100%; - margin: 0 auto; - padding: 20px 0; -} - -.forgot-password-modal { - background: url(/public/img/matecat_watch-left-border.png) no-repeat -34px - 136px; - background-size: 23%; - /*width: 385px;*/ - padding: 25px 96px; - text-align: right; -} - -.forgot-password-modal p { - text-align: left; -} - -.reset-password-modal { - padding: 5% 10%; - width: 80%; -} - .preference-modal-message { - box-shadow: 0 2px 2px #e2e2e2; + box-shadow: 0 2px 2px colors.$grey100; border-radius: 2px; - border: 1px solid #ccc; + border: 1px solid colors.$grey200; line-height: 20px; padding: 10px 15px; background: rgb(195, 224, 195); @@ -203,19 +154,19 @@ a { .matecat-modal-header { text-align: left; min-height: 50px; - border-radius: 4px 4px 0 0; + border-radius: 16px 16px 0 0; overflow: visible; max-height: inherit; font-size: 23px; - background: #002b5c; + background: colors.$blue900; padding: 7px 10px 7px 24px; background-size: 35px; - color: #fff; + color: colors.$white; margin: 0 !important; display: grid; - grid-template-columns: 40px 1fr 24px; + grid-template-columns: 40px 1fr 40px; position: relative; - grid-column-gap: 16px; + grid-column-gap: 8px; align-items: center; h2 { @@ -243,8 +194,8 @@ a { min-height: 50px; height: 100%; /*color: #000;*/ - background-color: colors.$grey5; - border-radius: 0 0 4px 4px; + background-color: colors.$grey50; + border-radius: 0 0 16px 16px; margin: 0 auto; overflow: hidden; text-align: left; @@ -303,8 +254,8 @@ a { left: 6px; bottom: 48px; top: unset; - width: 325px; - height: 342px; + width: 380px; + height: 350px; overflow: auto; background-color: unset; @@ -313,10 +264,10 @@ a { } .matecat-modal-content { - width: 320px; + width: 340px; min-width: unset; box-shadow: - 0 0 0 #e0e0e0, + 0 0 0 colors.$grey200, 0 0 2px rgba(0, 0, 0, 0.12), 0 2px 4px rgba(0, 0, 0, 0.24) !important; } @@ -327,15 +278,15 @@ a { border-radius: 4px 4px 0 0; overflow: visible; max-height: inherit; - background: #002b5c; + background: colors.$blue900; padding: 6px 10px 3px 24px; background-size: 31px; - color: #fff; + color: colors.$white; margin: 0 !important; display: grid; - grid-template-columns: 35px 1fr 24px; + grid-template-columns: 35px 1fr 40px; position: relative; - grid-column-gap: 16px; + grid-column-gap: 8px; h2 { font-size: 21px; @@ -357,17 +308,10 @@ a { .matecat-modal-top, .matecat-modal-bottom { - padding: 15px 17px; - } - - .ui.button { - font-size: 15px; - } - - .ui.button.cancel-button { - //margin-right: 45px; + padding: 15px 20px; } } + } .user-link { @@ -381,21 +325,6 @@ a { gap: 16px; } -/* The Close Button */ -.close-matecat-modal { - color: #fff; - float: right; - font-size: 20px; - font-weight: bold; -} - -.close-matecat-modal:hover, -.close-matecat-modal:focus { - color: red; - text-decoration: none; - cursor: pointer; -} - /* buttons */ .matecat-modal-content .disabled, @@ -405,7 +334,7 @@ a { cursor: default; -moz-box-shadow: none; -webkit-box-shadow: none; - border: 1px solid #666; + border: 1px solid colors.$grey700; } .matecat-modal-content .disabled, @@ -414,29 +343,7 @@ a { cursor: default; -moz-box-shadow: none; -webkit-box-shadow: none; - background: #d6d6d6; -} - -.x-popup, -.x-popup2 { - font-family: 'icomoon'; - speak: none; - font-style: normal; - font-weight: normal; - font-variant: normal; - text-transform: none; - line-height: 1; - /* Better Font Rendering =========== */ - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - &:hover { - color: colors.$darkBlueTransparent; - } -} - -.x-popup:before, -.x-popup2:before { - content: '\f057'; + background: colors.$grey200; } .matecat-modal-content, @@ -483,12 +390,12 @@ a { ::-webkit-scrollbar-thumb { -webkit-border-radius: 10px; border-radius: 10px; - background: #a7a5a5; + background: colors.$grey400; -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.5); } ::-webkit-scrollbar-thumb:window-inactive { - background: #a7a5a5; + background: colors.$grey400; } &.team { @@ -509,7 +416,7 @@ a { width: 40px !important; max-width: 40px; height: 40px; - background-color: colors.$grey2; + background-color: colors.$grey300; border-radius: 50%; vertical-align: middle; text-align: center; @@ -528,31 +435,31 @@ a { .content.email-user-invited { font-weight: 100; font-size: 14px; - color: colors.$grey1; + color: colors.$grey500; } .content.pending-msg { font-weight: 100; font-size: 14px; - color: colors.$grey1; + color: colors.$grey500; white-space: nowrap; } .mini.ui.button.right.floated { margin-top: 6px; - border: 1px solid #797979; + border: 1px solid colors.$grey600; display: inherit; border-radius: 2px; font-family: 'Calibri', 'Helvetica Neue', Arial, Helvetica, sans-serif; font-size: 14px; padding: 6px 15px; - background-color: #f6f6f6; + background-color: colors.$grey50; white-space: nowrap; &:hover { box-shadow: - 0 0 0 #e0e0e0, + 0 0 0 colors.$grey200, 0 0 2px rgba(0, 0, 0, 0.12), 0 2px 4px rgba(0, 0, 0, 0.24) !important; } @@ -567,7 +474,7 @@ a { } .mini.ui.primary.button { - border: 1px solid #797979; + border: 1px solid colors.$grey600; border-radius: 2px; font-family: 'Calibri', 'Helvetica Neue', Arial, Helvetica, sans-serif; @@ -582,7 +489,7 @@ a { } .ui.primary.button { - border: 1px solid #797979; + border: 1px solid colors.$grey600; border-radius: 2px; font-family: 'Calibri', 'Helvetica Neue', Arial, Helvetica, sans-serif; @@ -594,7 +501,7 @@ a { line-height: 20px; text-align: center; vertical-align: bottom; - border: 1px solid #797979; + border: 1px solid colors.$grey600; border-radius: 2px; } } @@ -619,6 +526,12 @@ a { } } } + .modal-buttons { + display: flex; + justify-content: flex-end; + width: 100%; + gap: 16px; + } } .matecat-modal-text { @@ -640,6 +553,13 @@ a { .check-conditions { margin-left: 5px; } + .buttons-container { + display: flex; + gap: 16px; + justify-content: flex-end; + width: 100%; + padding: 20px; + } } .pull-left { @@ -650,35 +570,15 @@ a { float: right !important; } -.create-team-modal, -.modify-team-modal, -.shortcuts-modal { - .create-team { - font-family: 'Calibri', 'Helvetica Neue', Arial, Helvetica, sans-serif; - padding: 11px 22px; - vertical-align: top; - font-size: 18px; - margin-right: 0px; - border-radius: 2px; - - &.primary.button { - border-radius: 2px; - } - } -} - -.modify-team-modal { -} - .ui.fluid.input > input { font-family: 'Calibri', 'Helvetica Neue', Arial, Helvetica, sans-serif; - box-shadow: inset 0 1px 3px #ddd; + box-shadow: inset 0 1px 3px colors.$grey200; font-size: 15px; } .ui.multiple.search.dropdown { width: 100%; - box-shadow: inset 0 1px 3px #ddd; + box-shadow: inset 0 1px 3px colors.$grey200; font-size: 15px; } @@ -686,7 +586,7 @@ a { height: 16px; &:hover { - color: #333333; + color: colors.$grey1300; } } @@ -708,7 +608,7 @@ a { .divider-line { height: 2px; width: 40%; - background-color: #c5c5c5; + background-color: colors.$grey200; margin-top: 10px; display: block; float: left; @@ -717,7 +617,7 @@ a { span { float: left; width: 20%; - color: #656565; + color: colors.$grey700; } } @@ -725,12 +625,11 @@ a { .message-modal { padding: 25px 0; } - .matecat-modal-buttons { + .modal-buttons { display: flex; - gap: 8px; justify-content: flex-end; - padding: 20px; width: 100%; + gap: 16px; } .matecat-modal-middle { @@ -739,7 +638,7 @@ a { .ui.primary.button, .ui.red.button { font-family: 'Calibri', 'Helvetica Neue', Arial, Helvetica, sans-serif; - border: 1px solid #797979; + border: 1px solid colors.$grey600; border-radius: 2px; } } @@ -793,7 +692,7 @@ a { .no-result { font-size: 14px; - color: #666666; + color: colors.$grey700; padding: 7px; } } @@ -803,7 +702,7 @@ a { .matecat-modal-top { .move-ribbon { - background: #e8e8e8; + background: colors.$grey100; padding: 8px 15px; border-radius: 4px; @@ -842,16 +741,16 @@ a { ::-webkit-scrollbar-thumb { -webkit-border-radius: 10px; border-radius: 10px; - background: #a7a5a5; + background: colors.$grey400; -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.5); } ::-webkit-scrollbar-thumb:window-inactive { - background: #a7a5a5; + background: colors.$grey400; } .default.text { - color: #000; + color: colors.$black; } } } @@ -879,7 +778,7 @@ a { h2 { padding-left: 10px; padding-bottom: 10px; - border-bottom: 1px solid #dee7e8; + border-bottom: 1px solid colors.$grey100; } .shortcut-item-list { @@ -892,7 +791,7 @@ a { } &:hover { - background: #f1f1f1; + background: colors.$grey75; } .shortcut-title, @@ -904,7 +803,7 @@ a { .shortcut-keys { .shortcuts { text-align: right; - color: #03bdee; + color: colors.$blue200; } .mac, @@ -915,7 +814,7 @@ a { display: inline-block; margin-left: 5px; margin-right: 5px; - background: #909798; + background: colors.$grey400; padding: 0 5px; line-height: 20px; font-size: 12px; @@ -1097,7 +996,7 @@ a { .buttons-popup-container { padding: 25px 0 30px; - border-bottom: 1px solid #f2f4f7; + border-bottom: 1px solid colors.$grey50; display: flex; gap: 20px; align-items: center; diff --git a/public/css/sass/common.scss b/public/css/sass/common.scss index b119bba6d1..80c5d807dc 100644 --- a/public/css/sass/common.scss +++ b/public/css/sass/common.scss @@ -81,11 +81,11 @@ ul { padding: 30px 0 30px 0; display: block; z-index: 999999; - background: #fff; - box-shadow: 0px 0px 5px #ccc; + background: colors.$white; + box-shadow: 0px 0px 5px colors.$grey200; border-radius: 2px; font-size: 18px; - border: 1px solid #ccc; + border: 1px solid colors.$grey200; } .iepopup img { @@ -94,7 +94,7 @@ ul { .iepopup ul a { padding: 0px 0 0 0; - color: #39699a; + color: colors.$blue400; text-decoration: underline; } @@ -140,7 +140,7 @@ section mark.searchMarker { } section mark.searchMarker.currSearchItem { - background: #f7d315; + background: colors.$orange200; /* background: #00c1e6; */ } @@ -163,8 +163,8 @@ section mark.searchMarker.currSearchItem { } .offline header { - background: #6d6e71; - border-bottom: 1px solid #333; + background: colors.$grey600; + border-bottom: 1px solid colors.$grey1300; padding: 0px 0 2px 0; margin-bottom: 20px; height: 45px; @@ -178,361 +178,15 @@ section mark.searchMarker.currSearchItem { } .offline h2 { - color: #999999 !important; + color: colors.$grey400 !important; font-weight: normal !important; } .claim span { font-weight: bold; - color: #39699a; -} - -.fileformat span { - padding: 10px 0px 10px 40px; - margin: 5px 0 0 0; - width: 100%; - height: 35px; - float: left; - background-size: 25px !important; -} - -.extdoc { - background: url(/public/img/matecat_file_icons.png) 6px 0 no-repeat !important; -} - -/* .doc, .dot, . docx, .dotx, .docm, .dotm, .odt, .sxw*/ -.extppt { - background: url(/public/img/matecat_file_icons.png) 6px -34px no-repeat !important; -} - -/* .pot, .pps, .ppt, .potm, .potx, .ppsm, .ppsx, .pptm, .pptx, .odp, .sxi*/ -.exthtm { - background: url(/public/img/matecat_file_icons.png) 6px -70px no-repeat !important; -} - -/* .htm, .html, .xhtml */ -.extpdf { - background: url(/public/img/matecat_file_icons.png) 6px -104px no-repeat !important; -} - -/* .pdf */ -.extxls { - background: url(/public/img/matecat_file_icons.png) 6px -140px no-repeat !important; -} - -/* .xls, .xlt, .xlsm, .xlsx, .xltx, .ods, .sxc, .csv */ -.exttxt { - background: url(/public/img/matecat_file_icons.png) 6px -172px no-repeat !important; -} - -/* .txt */ -.extxif { - background: url(/public/img/matecat_file_icons.png) 6px -208px no-repeat !important; -} - -/* .xliff */ -.extttx { - background: url(/public/img/matecat_file_icons.png) 6px -242px no-repeat !important; -} - -/* .ttx */ -.extitd { - background: url(/public/img/matecat_file_icons.png) 6px -276px no-repeat !important; -} - -/* .itd */ -.extxlf { - background: url(/public/img/matecat_file_icons.png) 6px -310px no-repeat !important; -} - -/* .xlf */ -.extmif { - background: url(/public/img/matecat_file_icons.png) 6px -342px no-repeat !important; -} - -/* .mif */ -.extidd { - background: url(/public/img/matecat_file_icons.png) 6px -378px no-repeat !important; -} - -/* .idml, .inx, .icml */ -.extqxp { - background: url(/public/img/matecat_file_icons.png) 6px -412px no-repeat !important; -} - -/* .xtg */ -.extxml { - background: url(/public/img/matecat_file_icons.png) 6px -446px no-repeat !important; + color: colors.$blue400; } -/* .xml */ -.extrcc { - background: url(/public/img/matecat_file_icons.png) 6px -484px no-repeat !important; -} - -/* .rc */ -.extres { - background: url(/public/img/matecat_file_icons.png) 6px -516px no-repeat !important; -} - -/* .resx */ -.extsgl { - background: url(/public/img/matecat_file_icons.png) 6px -552px no-repeat !important; -} - -/* .sgml */ -.extsgm { - background: url(/public/img/matecat_file_icons.png) 6px -584px no-repeat !important; -} - -/* .sgm */ -.extpro { - background: url(/public/img/matecat_file_icons.png) 6px -618px no-repeat !important; -} - -/* .properties */ -.extdit { - background: url(/public/img/matecat_file_icons.png) 6px -652px no-repeat !important; -} - -/* .dita */ -.exttag { - background: url(/public/img/matecat_file_icons.png) 6px -686px no-repeat !important; -} - -/* .tag */ -.exttmx { - background: url(/public/img/matecat_file_icons.png) 6px -722px no-repeat !important; -} - -/* .tmx */ -.extstr { - background: url(/public/img/matecat_file_icons.png) 6px -758px no-repeat !important; -} - -/* .str */ -.extzip { - background: url(/public/img/matecat_file_icons.png) 6px -792px no-repeat !important; -} - -/* .zip */ -.exticml { - background: url(/public/img/matecat_file_icons.png) 6px -826px no-repeat !important; -} - -/* .icml */ -.extimg { - background: url(/public/img/matecat_file_icons.png) 6px -860px no-repeat !important; -} - -/* .bmp, .gif, .jpeg, .png, .tiff */ -.extwix { - background: url(/public/img/matecat_file_icons.png) 6px -894px no-repeat !important; -} - -/* .wix */ -.extsrt { - background: url(/public/img/matecat_file_icons.png) 6px -928px no-repeat !important; -} - -/* .sbv */ -.extsbv { - background: url(/public/img/matecat_file_icons.png) 6px -1133px no-repeat !important; -} - -/* .vtt */ -.extvtt { - background: url(/public/img/matecat_file_icons.png) 6px -1167px no-repeat !important; -} - -/* .srt */ -.extpo { - background: url(/public/img/matecat_file_icons.png) 6px -962px no-repeat !important; -} - -/* .po */ -.extg { - background: url(/public/img/matecat_file_icons.png) 6px -996px no-repeat !important; -} - -/* .g */ -.exts { - background: url(/public/img/matecat_file_icons_ts.png) 6px -0px no-repeat !important; -} - -/* .ts */ -.extgsli { - background: url(/public/img/matecat_file_icons.png) 6px -1033px no-repeat !important; -} - -/* Google Slides */ -.extgdoc { - background: url(/public/img/matecat_file_icons.png) 6px -1070px no-repeat !important; -} - -/* Google Document */ -.extgsheet { - background: url(/public/img/matecat_file_icons.png) 6px -1107px no-repeat !important; -} - -/* retina display query */ -@media only screen and (-webkit-min-device-pixel-ratio: 2), - only screen and (min--moz-device-pixel-ratio: 2), - only screen and (-o-min-device-pixel-ratio: 2/1), - only screen and (min-device-pixel-ratio: 2), - only screen and (min-resolution: 192dpi), - only screen and (min-resolution: 2dppx) { - .preview span { - height: 30px; - width: 30px; - display: block; - background-size: 25px; - } - .extdoc { - background: url(/public/img/matecat_file_icons2x.png) 6px 0 no-repeat !important; - } - /* .doc, .dot, . docx, .dotx, .docm, .dotm, .odt, .sxw*/ - .extppt { - background: url(/public/img/matecat_file_icons2x.png) 6px -34px no-repeat !important; - } - /* .pot, .pps, .ppt, .potm, .potx, .ppsm, .ppsx, .pptm, .pptx, .odp, .sxi*/ - .exthtm { - background: url(/public/img/matecat_file_icons2x.png) 6px -70px no-repeat !important; - } - /* .htm, .html, .xhtml */ - .extpdf { - background: url(/public/img/matecat_file_icons2x.png) 6px -104px no-repeat !important; - } - /* .pdf */ - .extxls { - background: url(/public/img/matecat_file_icons2x.png) 6px -140px no-repeat !important; - } - /* .xls, .xlt, .xlsm, .xlsx, .xltx, .ods, .sxc, .csv */ - .exttxt { - background: url(/public/img/matecat_file_icons2x.png) 6px -172px no-repeat !important; - } - /* .txt */ - .extxif { - background: url(/public/img/matecat_file_icons2x.png) 6px -208px no-repeat !important; - } - /* .xliff */ - .extttx { - background: url(/public/img/matecat_file_icons2x.png) 6px -242px no-repeat !important; - } - /* .ttx */ - .extitd { - background: url(/public/img/matecat_file_icons2x.png) 6px -276px no-repeat !important; - } - /* .itd */ - .extxlf { - background: url(/public/img/matecat_file_icons2x.png) 6px -310px no-repeat !important; - } - /* .xlf */ - .extmif { - background: url(/public/img/matecat_file_icons2x.png) 6px -342px no-repeat !important; - } - /* .mif */ - .extidd { - background: url(/public/img/matecat_file_icons2x.png) 6px -378px no-repeat !important; - } - /* .idml, .inx, .icml */ - .extqxp { - background: url(/public/img/matecat_file_icons2x.png) 6px -412px no-repeat !important; - } - /* .xtg */ - .extxml { - background: url(/public/img/matecat_file_icons2x.png) 6px -446px no-repeat !important; - } - /* .xml */ - .extrcc { - background: url(/public/img/matecat_file_icons2x.png) 6px -484px no-repeat !important; - } - /* .rc */ - .extres { - background: url(/public/img/matecat_file_icons2x.png) 6px -516px no-repeat !important; - } - /* .resx */ - .extsgl { - background: url(/public/img/matecat_file_icons2x.png) 6px -552px no-repeat !important; - } - /* .sgml */ - .extsgm { - background: url(/public/img/matecat_file_icons2x.png) 6px -584px no-repeat !important; - } - /* .sgm */ - .extpro { - background: url(/public/img/matecat_file_icons2x.png) 6px -618px no-repeat !important; - } - /* .properties */ - .extdit { - background: url(/public/img/matecat_file_icons2x.png) 6px -652px no-repeat !important; - } - /* .dita */ - .exttag { - background: url(/public/img/matecat_file_icons2x.png) 6px -686px no-repeat !important; - } - /* .tag */ - .exttmx { - background: url(/public/img/matecat_file_icons2x.png) 6px -722px no-repeat !important; - } - /* .tmx */ - .extstr { - background: url(/public/img/matecat_file_icons2x.png) 6px -758px no-repeat !important; - } - /* .str */ - .extzip { - background: url(/public/img/matecat_file_icons2x.png) 6px -792px no-repeat !important; - } - /* .zip */ - .exticml { - background: url(/public/img/matecat_file_icons2x.png) 6px -826px no-repeat !important; - } - /* .icml */ - .extimg { - background: url(/public/img/matecat_file_icons2x.png) 6px -860px no-repeat !important; - } - /* .bmp, .gif, .jpeg, .png, .tiff */ - .extwix { - background: url(/public/img/matecat_file_icons2x.png) 6px -894px no-repeat !important; - } - /* .srt */ - .extsrt { - background: url(/public/img/matecat_file_icons2x.png) 6px -928px no-repeat !important; - } - /* .sbv */ - .extsbv { - background: url(/public/img/matecat_file_icons2x.png) 6px -1133px no-repeat !important; - } - /* .vtt */ - .extvtt { - background: url(/public/img/matecat_file_icons2x.png) 6px -1167px no-repeat !important; - } - /* .po */ - .extpo { - background: url(/public/img/matecat_file_icons2x.png) 6px -962px no-repeat !important; - } - /* .po */ - .extg { - background: url(/public/img/matecat_file_icons2x.png) 6px -996px no-repeat !important; - } - /* .g */ - .exts { - background: url(/public/img/matecat_file_icons_ts2x.png) 6px 0px no-repeat !important; - } - /* .ts */ - .extgsli { - background: url(/public/img/matecat_file_icons2x.png) 6px -1033px no-repeat !important; - } - /* Google Slides */ - .extgdoc { - background: url(/public/img/matecat_file_icons2x.png) 6px -1070px no-repeat !important; - } - /* Google Document */ - .extgsheet { - background: url(/public/img/matecat_file_icons2x.png) 6px -1107px no-repeat !important; - } - /* Google Sheet */ -} @font-face { font-family: 'icomoon'; @@ -565,28 +219,20 @@ icon-iconmoon:before, .sorting_asc:after, .open-popup-addtm-tr:before, .sorting:after, -.x-popup:before, -.x-popup2:before, -.popup .x-popup:before, -.mgmt-panel .x-popup:before, -.popup-tm .x-popup:before, td.actions a:before, a.archive-project:before, a.unarchive-project:before, a.unarchive-project:after, .splitpoint:before, -.notific:before, #swaplang:after, .more:before, .more.minus:before, .close:before, -.notific.error:before, .breadcrumbs #pname:before, .delete button:before, .cancel button:before, .graysmall:hover .trash:before, .splitpoint-delete:after, -#point2seg:after, .warnings:before, /* mbc chat */ .mbc-warnings:before, @@ -625,29 +271,14 @@ header .filter:before { vertical-align: middle; } -.notific:before { - content: '\f058'; - font-size: 25px; -} - -.notific.error:before { - content: '\f071'; - font-size: 25px; -} - .warnings:before, .mbc-warnings:before, .text .alternatives:before { content: '\f071'; - color: #d65959; + color: colors.$red400; margin-right: 10px; } -#point2seg:after { - content: '\e903'; - font-size: 24px; -} - #swaplang:after { content: '\f0ec'; } @@ -696,11 +327,6 @@ a.unarchive-project:after { transform: rotate(-45deg); } -.x-popup:before, -.x-popup2:before { - content: '\f057'; -} - .open-popup-addtm-tr:before { content: '\e602'; padding-right: 5px; @@ -1043,7 +669,7 @@ a.unarchive-project:after { } #menu-site li a { - color: #fff; + color: colors.$white; text-decoration: none; -webkit-font-smoothing: antialiased; line-height: 22px; @@ -1055,9 +681,9 @@ a.unarchive-project:after { #menu-site li a.bigblue { font-size: 17px !important; border: none !important; - color: colors.$darkBlue !important; + color: colors.$blue900 !important; border-radius: 18px; - background-color: #fff; + background-color: colors.$white; padding: 4px 18px; font-weight: bold; margin-left: 5px; @@ -1065,17 +691,11 @@ a.unarchive-project:after { } #menu-site li a.bigred:hover { - color: colors.$darkBlueHover !important; + color: colors.$blue950 !important; } #menu-site li a:hover { - color: #3aa9dd; -} - -.ui.primary.button.button-modal.warning-button.orange.margin.left-10.right-20 { - height: 43px; - padding: 1px 10px; - font-size: 15px; + color: colors.$blue500; } /*****************************/ @@ -1098,7 +718,7 @@ body svg { > span { display: block; text-align: center; - background-color: colors.$grey7; + background-color: colors.$grey400; border-radius: 4px; padding: 2px 4px; color: colors.$white; diff --git a/public/css/sass/commons/_analyze.scss b/public/css/sass/commons/_analyze.scss index e3bba4c5b6..07a00044cf 100644 --- a/public/css/sass/commons/_analyze.scss +++ b/public/css/sass/commons/_analyze.scss @@ -1,35 +1,39 @@ -@use '../commons/colors'; +@use './colors'; +@use '../commons/variables'; // rewrite semantic CSS html, body { height: 100%; } + body.analyze { min-width: 1024px; - font-family: Calibri, Arial, Helvetica, sans-serif; - background-color: colors.$grey5; + background-color: colors.$grey100; overflow-x: auto; overflow-y: hidden; - font-size: 14px; - h1 { - font-size: 28px; - } + font: variables.$font-style-base; } + .analyze-page { height: 100%; } + .project-list { - height: 100%; - positon: relative; + height: calc(100% - 60px); + position: relative; overflow-y: auto; } + .project-list { padding-top: 40px; /* was 62px with previous header */ padding-bottom: 160px; .project { + display: flex; + flex-direction: column; + gap: 16px; .scroll { - background-color: colors.$grey2; + background-color: colors.$grey300; width: 40px; height: 40px; position: fixed; @@ -40,9 +44,11 @@ body.analyze { outline: none; opacity: 0.8; z-index: 3; + &:hover { opacity: 1; } + i { margin-left: -7px; font-size: 22px; @@ -51,187 +57,140 @@ body.analyze { } .project-header { - background: colors.$grey4; - padding-bottom: 10px; - margin-bottom: 0; + display: flex; + gap: 16px; + .left-analysis { - padding-top: 20px; - padding-left: 30px; - top: 14px; - position: relative; - width: 55% !important; - height: 205px; - .h1 { - font-size: 38px; - font-weight: 100; - color: grey; - margin-bottom: 0; - } - .ui.ribbon.label { - position: relative; - top: 0; - z-index: 2; - left: -45px; - max-width: 100%; - min-width: 0; - background-color: colors.$grey2; - color: #000000; - border-radius: 0 2px 2px 0; - padding-right: 15px; - &:after { - border-right-color: colors.$grey1 !important; - } - .project-id, - .project-name { - display: inline-block; - vertical-align: text-bottom; - position: relative; - } - .project-id { - font-size: 14px; - font-weight: 700; - margin-right: 5px; - margin-left: 15px; - color: #5a5a5a; - top: -2px; - } - .project-name { - font-size: 20px; - max-width: 100%; - min-width: 30px; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - top: 1px; - padding-left: 15px; - } - } - .project-create { - top: 10px; - position: relative; - font-size: 18px; + display: flex; + padding: 16px 24px; + flex-direction: column; + justify-content: center; + align-items: flex-start; + gap: 16px; + flex: 1 0 0; + border-radius: variables.$border-radius-big; + border: 1px solid colors.$grey150; + background: colors.$grey50; + .project-name h5 { + font-weight: 700; + line-height: 28px; } .analysis-create { - margin-top: 35px; + display: flex; + align-items: center; font-size: 16px; - .search-tm-matches { - .loader { - margin-right: 5px; - } - h5 { - display: inline-block; - margin-bottom: 0; - span { - color: colors.$greenDefault; - padding: 5px 2px 5px 0; - margin-left: 4px; - border-radius: 15px; - } - i { - color: colors.$greenDefault; - position: relative; - top: 2px; + width: 100%; + .loader { + margin-right: 5px; + } + .analysis-progressbar { + width: 100%; + .progress-wrapper { + background-color: rgba(colors.$blue500, 0.24); + .progress { + background-color: colors.$blue500; } } - .complete { - display: inline-block; - font-size: 18px; - line-height: 18px; - .number { - font-weight: 700; - } - a { - font-weight: 700; - text-decoration: underline; - &:hover { - text-decoration: none; - } - } + } + .not-complete.failed { + padding-left: 15px; + border-left: 1px solid colors.$grey300; + margin-left: 15px; + } + .complete { + display: flex; + align-items: center; + gap: 8px; + + .number { + font-weight: 700; } - .downloadAnalysisReport { - display: inline-block; - border-left: 1px solid black; - padding-left: 10px; - color: black; + + a { + font-weight: 700; text-decoration: underline; - margin-left: 10px; - cursor: pointer; + &:hover { text-decoration: none; } } - .analysisNotPerformed { - font-size: 18px; - line-height: 18px; - display: inline-block; - } } - } - } + .not-complete { - .word-count { - .word-percent { - position: relative; - padding: 15px 15px 10px 20px; - border: 1px solid colors.$greenDefault; - top: 27px; - font-size: 16px; - margin-bottom: 25px; - .percent { - font-size: 40px; - font-weight: 700; - display: inline-block; - vertical-align: -webkit-baseline-middle; - margin-right: 10px; } - .content { - font-size: 20px; - .sub.header { - font-size: 12px; - } - } - a { + + .downloadAnalysisReport { + display: flex; + gap: 8px; + border-left: 1px solid colors.$grey300; + color: colors.$linkBlue; text-decoration: underline; - font-weight: 700; + margin-left: 16px; cursor: pointer; + padding-left: 16px; + align-items: center; &:hover { text-decoration: none; - } - &:active { - text-decoration: none; - } - &:focus { - text-decoration: none; + color: colors.$linkBlueHover; } } } - .word-raw, - .matecat-raw { - background-color: #f2f4f1; - padding: 5px; - border: 1px solid #7eaf3e; - text-align: center; - transition: 0.4s ease; - h3, - h4 { - margin: 0; + + } + + .word-count { + display: flex; + width: 360px; + //height: 100px; + padding: 16px 24px; + justify-content: space-between; + align-items: center; + border-radius: variables.$border-radius-big; + border: 1px solid colors.$grey150; + background: colors.$grey50; + .percent { + display: flex; + align-items: center; + gap: 12px; + align-self: stretch; + &.in-progress h2 { + color: colors.$blue500; } - h3 { - font-size: 28px; + } + .content { + display: flex; + flex-direction: column; + justify-content: center; + align-items: flex-start; + font: variables.$font-style-small; + .work-hour { + color: colors.$grey400; } } - .word-raw { + svg { + color: colors.$grey800; } - .overlay { - background-color: rgba(243, 243, 243, 0.6); - border: 1px solid #a7c3a7; - margin-top: -67px; - z-index: 10; - position: relative; - height: 100%; + a { + text-decoration: underline; + font-weight: 700; + cursor: pointer; + + &:hover { + text-decoration: none; + } + + &:active { + text-decoration: none; + } + + &:focus { + text-decoration: none; + } } + + .updated-count { - background-color: #f9ffb5; + background-color: colors.$orange50; } } @@ -243,851 +202,166 @@ body.analyze { padding: 15px; border: 1px solid green; border-radius: 0; + .percent { vertical-align: middle; display: inline-block; } } - .progress { - padding: 0 15px; - top: 5px; - .progress-bar { - width: 100%; - } - } } .project-top { - padding: 45px 15px 15px; - background-color: colors.$grey5; - margin: 0 -1rem 0; + &.type-mtqe { .title-total-words, .title-matecat-words { width: 50% !important; } } - .compare-table { - background-color: colors.$grey3; - margin-bottom: 1px; - .updated-count { - background-color: #f9ffb5; - transition: 0.4s ease; - } - .header-compare-table, - .jobs-compare-table { - h5 { - margin-bottom: 0; - font-weight: 100; - font-size: 14px; - } - p { - font-size: 12px; - } - } - .header-compare-table { - //padding-top: 15px; - //padding-bottom: 15px; - z-index: 1; - position: relative; - } - .title-job { + + + } + + .project-top.type-standard { + display: flex; + flex-direction: column; + gap: 16px; + .project-card { + display: flex; + flex-direction: column; + align-items: flex-start; + align-self: stretch; + border-radius: variables.$border-radius-big; + border: 1px solid colors.$grey150; + overflow: hidden; + .project-card__header, .project-card__content { display: flex; - flex-flow: inherit; + padding: 0 24px; align-items: center; - justify-content: flex-start; - width: 28%; - /*line-height: 50px;*/ - /*text-align: left;*/ - font-size: 16px; - padding: 10px 24px; - /*margin-right: 0;*/ - - &.splitted { - width: 28%; - &.heading { - width: 80%; - justify-content: flex-start; - } - &:not(.heading) { - .job-id { - width: 85%; - margin-bottom: 12px; - } - } - } - .job-info { + gap: 32px; + align-self: stretch; + } + .project-card__header-info { + display: flex; + width: 300px; + flex-direction: column; + align-items: flex-start; + .project-card__chunkName { + margin-bottom: 4px; + font: variables.$font-style-small; + } + .project-card__header-link { display: flex; - justify-content: flex-start; width: 100%; - margin-bottom: 12px; - } - &.splitted { - .job-info { - margin-bottom: 0; - } - } - .translate-url { - display: inline-flex; - width: 100%; - .copy { - .icon { - height: 100%; - width: 100%; - font-size: 18px; - font-weight: 700; - padding: 2px; - } - } - span { - display: flex; - } + padding: 4px 8px; + justify-content: center; + align-items: center; + gap: 8px; + border-radius: variables.$border-radius-default; + background: colors.$grey50; + color: colors.$blue500; input { - outline: none; - border: 1px solid #bbbbbb; - padding: 4px; - color: #0099cc; - font-size: 12px; - font-weight: 700; - white-space: nowrap; + all: unset; + overflow: hidden; text-overflow: ellipsis; - border-radius: 2px 0 0 2px; - border-right: none; - min-width: 200px; - height: 24px; + font: variables.$font-style-xsmall; + white-space: nowrap; width: 100%; } - button { - border: 1px solid #bbbbbb; - background-color: #ffffff; - color: #0099cc; - text-align: center; - text-decoration: none; - border-radius: 0 2px 2px 0; - height: 24px; - min-width: 24px; - padding: 0; - margin: 0; - i { - margin: 2px 0 0 0; - } - } } - } - .titles-compare { - display: flex; - align-items: center; - width: 38%; - text-align: center; - padding-left: 0; - padding-right: 0; - font-size: 16px; - } - .title-total-words, - .title-standard-words, - .title-matecat-words { - display: flex; - align-items: center; - justify-content: center; - width: 33.333%; - border-right: 1px solid #d7d8dc; - /*border-left: 1px solid #d7d8dc;*/ - /*margin-left: -1px;*/ - /*line-height: 100px;*/ - padding-top: 15px; - padding-bottom: 15px; - height: 100%; - &:first-child { - border-left: 1px solid #d7d8dc; - } - } - .title-standard-words { - h5 { + .project-card__header-languages { + display: flex; + align-items: center; + gap: 4px; span { - color: #a7a7a7; - font-weight: 100; - position: relative; - top: 2px; - left: 2px; + font-weight: 700; } - } - .title-standard-words-help-icon { - cursor: help; - svg { - color: colors.$linkBlue; + color: colors.$grey700; } } - } - .title-matecat-words { - h5 { - font-weight: 700; + .project-card__header-id { + font: variables.$font-style-xsmall; + color: colors.$grey700 } } - &.jobs { - background-color: colors.$grey5; - z-index: 0; - position: relative; - .job { - margin-bottom: 15px; - .chunks { - .chunk { - background-color: #ffffff; - transition: 0.3s ease; - cursor: pointer; - /*padding: 16px 8px;*/ - .job-details { - font-size: 15px; - float: right; - top: 11px; - color: #4183c4; - text-decoration: underline; - font-weight: 700; - margin-left: 5px; - cursor: pointer; - display: inline-block; - &:hover { - text-decoration: none; - } - } - &:hover { - background-color: #f6f6f9; - .title-matecat-words { - background: #f6ffe9 !important; - transition: 0.3s ease; - } - } - .ttw, - .tsw, - .tmw { - text-align: center; - /*padding-right: 15px;*/ - color: #788190; - padding-top: 0; - padding-bottom: 0; - .cell-label { - float: left; - margin-left: 15px; - font-weight: 100; - font-size: 16px; - } - } - .tmw { - font-weight: 700; - font-size: 18px; - margin-bottom: 1px; - color: #788190; - .cell-label { - text-decoration: underline; - cursor: pointer; - color: #646760; - &:hover { - text-decoration: none; - } - } - i { - font-size: 23px; - top: 4px; - position: relative; - float: right; - margin-left: 5px; - margin-top: 9px; - } - } - } - } - } + .project-card__header-actions { + display: flex; + width: 334px; + justify-content: flex-end; + align-items: center; + gap: 4px; } - .activity-icons { - width: 34%; + .project-card__count { display: flex; + justify-content: flex-end; align-items: center; - justify-content: space-evenly; - text-align: center; - padding: 0 4px; - - /*margin-left:8px;*/ - .ui.primary.button, - .ui.basic.blue.button { - min-width: 120px !important; - height: 34px; - } - .activity-button { + gap: 16px; + flex: 1 0 0; + > div { display: flex; - width: 68%; - padding: 0 4px; + width: 160px; justify-content: flex-end; - border-right: 1px solid #bbbbbb; - padding: 8px; - .button { - width: 45%; - } - &.disable-outsource { - border-right: none; - justify-content: center; - } - } - .outsource-translation { - display: flex; align-items: center; - justify-content: center; - width: 32%; - flex-flow: column; - height: 100%; - &.outsource-translation-disabled { - span, - a { - color: colors.$grey; - } - } - a { - color: #09beec; - text-decoration: underline; - } - span { - color: #000; - font-size: 10px; - display: flex; - justify-content: center; - align-items: end; - line-height: 15px; - svg { - margin-left: 2px; - } - } - } - .split { - display: flex; - align-items: center; - justify-content: space-evenly; - } - .split, - .merge { - font-family: Calibri, Arial, Helvetica, sans-serif; - padding: 5px 20px; //padding: 8px 16px; - vertical-align: top; - font-size: 19px; //font-size: 16px; - border: 1px solid #09beec; - border-radius: 2px; - box-shadow: none !important; - background-color: #ffffff !important; - font-weight: 700; //font-weight: normal; - /*margin-top: -3px;*/ - &:hover { - text-decoration: none; - box-shadow: - 0 0 0 #e0e0e0, - 0 0 2px rgba(0, 0, 0, 0.12), - 0 2px 4px rgba(0, 0, 0, 0.24) !important; - border: 1px solid #09beec; - } - &:focus { - box-shadow: none !important; - background-color: #f2f2f2 !important; - } - &:active { - box-shadow: none !important; - background-color: #f2f2f2 !important; - } - } - - .merge { - margin: -3px 0 0; - padding: 5px 14px; - width: 54%; - } - .open-translate, - .open-revise { - font-family: Calibri, Arial, Helvetica, sans-serif; - padding: 6px 15px; // padding: 8px 16px; - vertical-align: top; - font-size: 20px; //font-size: 16px; - border: 1px solid #797979; //border: none; - border-radius: 2px; - /*margin: -3px 0 0 0;*/ - font-weight: 700; //font-weight: normal; - } + gap: 4px; + color: colors.$grey700; - &.splitted { - width: 20%; - justify-content: flex-end; - padding: 0 8px; - } - - @media only screen and (max-width: 1199px) { - .ui.primary.button, - .ui.basic.blue.button { - min-width: 100px !important; - height: 34px; - } - .merge { - padding: 5px 12px; - } - .split { - padding: 5px 12px; - i { - margin: 0; - } - } - - .open-translate { - font-family: Calibri, Arial, Helvetica, sans-serif; - padding: 5px 12px; + &:last-child { + font-weight: 700; + color: colors.$black; } } - } - .openOutsource { - .title-job, - .titles-compare, - .activity-icons { - display: none; - } - } - } - .analyze-report { - text-align: center; - width: 100%; - background-color: colors.$grey3; - margin: 0 auto; - position: relative; - top: 30px; - cursor: pointer; - z-index: 1; - > div { - width: 160px; - margin: 0 auto; - position: relative; - height: 48px; - display: flex; - } - h3 { - margin-bottom: 10px; - color: #000; - float: left; - margin-top: 10px; - } - .rounded { - width: 35px; - height: 35px; - line-height: 0; - border-radius: 17px; - cursor: pointer; - transition: 0.3s ease; - float: left; - i { - font-size: 30px; - margin: 0; - padding: 0; - top: 3px; - position: relative; - transition: 0.3s ease; - color: colors.$black; - &.open { - -webkit-transform: rotate(180deg); - -moz-transform: rotate(180deg); - -ms-transform: rotate(180deg); - -o-transform: rotate(180deg); - transform: rotate(180deg); - top: 11px; - } - } - } - } - } - .job-id { - display: inline-block; - color: colors.$grey1; - font-size: 12px; - position: relative; - line-height: 35px; - top: 1px; - text-align: left; - margin-right: 5px; - min-width: 70px; - } - .source-target { - display: inline-block; - font-weight: bold; - max-width: 76%; - vertical-align: middle; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - font-size: 16px; - line-height: 32px; - .source-box { - /*line-height: 30px;*/ - display: inline-block; - max-width: 50%; - min-width: 60px; - vertical-align: middle; - overflow: hidden; - text-overflow: ellipsis; - &.no-split { - max-width: 40%; } - } - .in-to { - display: inline-block; - top: 3px; - color: #5a5a5a; - /*line-height: 28px;*/ - width: 24px; - position: relative; - i { - margin-right: 0; - font-size: 12px; - top: -2px; - position: relative; - } - } - .target-box { - display: inline-block; - /*line-height: 30px;*/ - max-width: 50%; - min-width: 60px; - vertical-align: middle; - overflow: hidden; - text-overflow: ellipsis; - &.no-split { - max-width: 43%; - } - } - } - - @media only screen and (max-width: 1199px) and (min-width: 992px) { - .source-target { - /*max-width: 68% !important;*/ - .source-box, - .target-box { - max-width: 50%; - min-width: 50px; - vertical-align: middle; - overflow: hidden; - text-overflow: ellipsis; - /*&.no-split { - max-width: 40%; - min-width: 50px; - vertical-align: middle; - overflow: hidden; - text-overflow: ellipsis; - }*/ - } - } - } - - .project-body { - margin-top: 0; - background-color: colors.$grey3; - margin: 0 -1rem 0; - margin-left: 1px; - margin-right: 1px; - .job { - padding: 0 15px; - margin-top: 35px; - margin-bottom: 20px; - .job-header { - background-color: colors.$white !important; - padding: 0 0 !important; - } - .job-body { - background-color: colors.$grey5; - .chunks { - overflow-x: auto; - .chunk-container { - padding-top: 0; - overflow-x: auto; - min-width: 1200px; - .analysis { - //padding-top: 60px; - margin-top: 0; - &.show-details { - .chunks-analyze, - .chunk-analyze-container > div { - background-color: colors.$grey4 !important; - } - } - &.outsource-open { - margin-left: -35px; - margin-right: -35px; - } - } - } + @media screen and (max-width: 1300px) { + .project-card__count > div { + width: 140px } - } - } - } - } -} - -/*.analysis { - .chunk-detail { - .left-box { - height: 1%; - position: relative; - float: left; - text-align: left; - width: 15%; - } - .right-box { - width: 10%; - position: relative; - float: right; - top: 2px; - } - - @media only screen and (max-width: 1199px) and (min-width: 992px) { - .left-box { - padding-left: 0 !important; - .job-id { - min-width: 65px; - } - .file-details { - text-decoration: underline; - min-width: 25px; - line-height: 35px; - font-weight: 700; - position: relative; - top: 1px; - .details { - display: none; + .project-card__header-info { + width: 200px; } - &:hover { - text-decoration: none; - } - } - .f-details-number { - display: inline-block; } - } - } - - @media only screen and (max-width: 991px) and (min-width: 768px) { - .left-box { - padding-left: 0 !important; - .job-id { - min-width: 65px; - } - .file-details { - text-decoration: underline; - min-width: 25px; - line-height: 35px; - font-weight: 700; - position: relative; - top: 1px; - .details { - display: none; + @media screen and (max-width: 1200px) { + .project-card__count > div { + width: 140px } - &:hover { - text-decoration: none; + .project-card__header-info { + width: 150px; } } - } - } - - @media only screen and (max-width: 767px) { - .left-box { - padding-left: 0 !important; - .job-id { - min-width: 65px; + .project-card__header { + height: 64px; + background: colors.$grey50; } - .file-details { - text-decoration: underline; - min-width: 25px; - line-height: 35px; - font-weight: 700; - position: relative; - top: 1px; - .details { - display: none; - } - &:hover { - text-decoration: none; - } + .project-card__content { + height: 80px; + border-bottom: 1px solid colors.$grey100; + background: colors.$white; } } } - } - .chunk-detail { - transition: 0.3s ease; - background-color: #ffffff; - padding-top: 4px !important; - padding-bottom: 4px !important; - text-align: center; - } - - .chunk-detail { - padding-top: 0 !important; - padding-bottom: 0 !important; - background-color: $grey2; - padding-left: 12px; - z-index: 0; - .left-box { - padding-top: 8px; - i { - position: absolute; - top: 12px; + .project-body { + background-color: colors.$grey50; + display: flex; + padding: 8px 16px 16px 16px; + flex-direction: column; + align-items: flex-start; + gap: 8px; + align-self: stretch; + border-radius: variables.$border-radius-big; + h5 { + font-size: 16px; } - .file-title-details { - display: inline-block; - max-width: 82%; - min-width: 30px; - white-space: nowrap; + .job { + display: flex; + flex-direction: column; + align-items: flex-start; + align-self: stretch; + border-radius: variables.$border-radius-default; + border: 1px solid colors.$grey150; overflow: hidden; - text-overflow: ellipsis; - position: absolute; - transition: 0.3s ease; - position: absolute; - left: 18px; - cursor: default; - &:hover { - display: inline-block; - max-width: 210%; - min-width: 30px; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - position: absolute; - left: 18px; - background: #c7c6c6; - padding: 0 5px; - z-index: 2; - } } } } - .updated-count { - background-color: #f9ffb5; - transition: 0.4s ease; - } -}*/ - -@media only screen and (min-width: 1200px) { - .ui.container:not(.fluid) { - width: 1140px !important; - margin-left: auto !important; - margin-right: auto !important; - transition: 0.3s ease; - } -} - -@media only screen and (min-width: 1380px) { - .ui.container:not(.fluid) { - width: 1280px !important; - margin-left: auto !important; - margin-right: auto !important; - transition: 0.3s ease; - } -} - -@media only screen and (max-width: 1199px) and (min-width: 992px) { - .ui.container:not(.fluid) { - width: 991px !important; - margin-left: auto !important; - margin-right: auto !important; - transition: 0.3s ease; - } -} - -@media only screen and (max-width: 991px) and (min-width: 768px) { - .ui.container:not(.fluid) { - min-width: 991px !important; - margin-left: auto !important; - margin-right: auto !important; - transition: 0.3s ease; - } - .project-list { - padding-top: 50px; - } -} - -@media only screen and (max-width: 767px) { - .ui.container:not(.fluid) { - margin-left: 1em !important; - margin-right: 1em !important; - min-width: 991px; - transition: 0.3s ease; - } - .project-list { - padding-top: 50px; - } -} - -// Transitions -/*.chunk-detail { - width: 100%; - height: 35px; - position: relative; - overflow: hidden; - &.transition-enter { - height: 0; - padding-top: 0px !important; - padding-bottom: 0 !important; - } - - &.transition-enter.transition-enter-active { - height: 35px; - -webkit-transition: height 0.3s ease; - } - - &.transition-exit.transition-exit-active { - height: 0; - padding-top: 0px !important; - padding-bottom: 0 !important; - -webkit-transition: height 0.3s ease; - } -}*/ -.progress-bar { - height: 20px; - position: relative; - overflow: hidden; - &.transition-enter { - height: 0; - padding-top: 0px !important; - padding-bottom: 0 !important; - } - - &.transition-enter.transition-enter-active { - height: 20px; - -webkit-transition: height 0.3s ease; - } - - &.transition-exit.transition-exit-active { - height: 0; - padding-top: 0px !important; - padding-bottom: 0 !important; - -webkit-transition: height 0.3s ease; - } -} - -.project { - .jobs { - position: relative; - opacity: 1; - } - .transitionAnalyzeMain-enter { - max-height: 0; - opacity: 0; - } - - .transitionAnalyzeMain-enter.transitionAnalyzeMain-enter-active { - max-height: 3000px; - opacity: 1; - -webkit-transition: - max-height 0.5s ease, - opacity 1s ease; - } - - .transitionAnalyzeMain-exit.transitionAnalyzeMain-exit-active { - max-height: 0; - padding-top: 0; - padding-bottom: 0; - opacity: 0; - -webkit-transition: - max-height 0.5s ease, - padding 1s ease, - opacity 1s ease; - } } diff --git a/public/css/sass/commons/_aria-label-tooltip.scss b/public/css/sass/commons/_aria-label-tooltip.scss index 8030316434..eef78b505d 100644 --- a/public/css/sass/commons/_aria-label-tooltip.scss +++ b/public/css/sass/commons/_aria-label-tooltip.scss @@ -13,7 +13,7 @@ padding: 4px 8px; background-color: colors.$white; box-shadow: 0 0 16px rgba(colors.$black, 0.25); - color: colors.$grey6; + color: colors.$grey700; pointer-events: none; white-space: pre; font-size: 14px; @@ -64,7 +64,7 @@ } [aria-label][tooltip-position='bottom']::before { bottom: -6px; - border-bottom: 6px solid colors.$grey4; + border-bottom: 6px solid colors.$grey100; } [aria-label][tooltip-position='left']::before, @@ -81,7 +81,7 @@ } [aria-label][tooltip-position='left']::before { left: -6px; - border-left: 6px solid colors.$grey4; + border-left: 6px solid colors.$grey100; } [aria-label][tooltip-position='right']::after { top: 50%; @@ -90,5 +90,5 @@ } [aria-label][tooltip-position='right']::before { right: -6px; - border-right: 6px solid colors.$grey4; + border-right: 6px solid colors.$grey100; } diff --git a/public/css/sass/commons/_buttons.scss b/public/css/sass/commons/_buttons.scss index 166d502280..1df914d0a7 100644 --- a/public/css/sass/commons/_buttons.scss +++ b/public/css/sass/commons/_buttons.scss @@ -20,13 +20,13 @@ linear, left top, left bottom, - from(colors.$translatedBlue), - to(#119ec4) + from(colors.$blue500), + to(colors.$blue500) ); - background: -moz-linear-gradient(top, colors.$translatedBlue, #119ec4); - background: linear-gradient(top, colors.$translatedBlue, #119ec4); - color: #fff; - border: 1px solid #848689; + background: -moz-linear-gradient(top, colors.$blue500, colors.$blue500); + background: linear-gradient(top, colors.$blue500, colors.$blue500); + color: colors.$white; + border: 1px solid colors.$grey500; text-decoration: none; border-radius: 2px; &.disabled { @@ -34,51 +34,51 @@ cursor: default; -moz-box-shadow: none; -webkit-box-shadow: none; - border: 1px solid #666; - background: #ccc; + border: 1px solid colors.$grey700; + background: colors.$grey200; } } &.grey { - color: #333; - background: #f6f6f6; + color: colors.$grey1300; + background: colors.$grey50; background: -webkit-gradient( linear, left top, left bottom, - from(#f6f6f6), - to(#e2e3e5) + from(colors.$grey50), + to(colors.$grey100) ); - background: -moz-linear-gradient(top, #f6f6f6, #e2e3e5); - background: linear-gradient(top, #f6f6f6, #e2e3e5); - border: 1px solid #848689; + background: -moz-linear-gradient(top, colors.$grey50, colors.$grey100); + background: linear-gradient(top, colors.$grey50, colors.$grey100); + border: 1px solid colors.$grey500; text-decoration: none; border-radius: 2px; } &.orange { - background-color: #f26522; + background-color: colors.$orange700; background: -webkit-gradient( linear, left top, left bottom, - from(#f26522), - to(#fb5d12) + from(colors.$orange700), + to(colors.$orange900) ); - background: -moz-linear-gradient(top, #f26522, #fb5d12); - background: linear-gradient(top, #f26522, #fb5d12); - color: #fff; - border: 1px solid #848689; + background: -moz-linear-gradient(top, colors.$orange700, colors.$orange900); + background: linear-gradient(top, colors.$orange700, colors.$orange900); + color: colors.$white; + border: 1px solid colors.$grey500; text-decoration: none; border-radius: 2px; } &:hover { - box-shadow: 0 1px 2px #ccc; - -webkit-box-shadow: 0 1px 2px #ccc; - border: 1px solid #000; + box-shadow: 0 1px 2px colors.$grey200; + -webkit-box-shadow: 0 1px 2px colors.$grey200; + border: 1px solid colors.$black; } &:active { - -moz-box-shadow: inset 0 0 1px 1px #888; - -webkit-box-shadow: inset 0 0 1px 1px #888; - box-shadow: inset 0 0 1px 1px #888; + -moz-box-shadow: inset 0 0 1px 1px colors.$grey400; + -webkit-box-shadow: inset 0 0 1px 1px colors.$grey400; + box-shadow: inset 0 0 1px 1px colors.$grey400; } &.margin { @@ -102,51 +102,3 @@ } } } - -.ui.button.cancel-button { - font-family: 'Calibri', 'Helvetica Neue', Arial, Helvetica, sans-serif; - margin-top: 0; - border: 1px solid #797979; - border-radius: 2px; - background-color: #f6f6f6; - margin-right: 15px; - &:hover { - //box-shadow: 0 0 0 #e0e0e0, 0 0 2px rgba(0, 0, 0, 0.12), 0 2px 4px rgba(0, 0, 0, 0.24) !important; - } - &:focus { - box-shadow: none; - } -} - -// Button TR, LR navigation through filter -.ui.next-repetition-group, -.ui.next-repetition { - border: 1px solid #797979; - position: relative; - padding: 9px 12px 8px !important; -} - -.ui.next-review-repetition-group, -.ui.next-review-repetition { - border: 1px solid #797979; - position: relative; - padding: 9px 12px 8px !important; - background: colors.$approvedGreen !important; - &.revise-button-2 { - background: #bc6ac9 !important; - } -} - -.ui.next-repetition-group, -.ui.next-review-repetition-group { - margin-right: 4px; -} - -// Button comment segment -.ui.primary.mbc-comment-send-btn { - font-size: 14px; - padding: 8px 10px; - text-align: right; - border-radius: 2px; - float: right; -} diff --git a/public/css/sass/commons/_colors.scss b/public/css/sass/commons/_colors.scss index cade3f7d45..d315d7ff3c 100644 --- a/public/css/sass/commons/_colors.scss +++ b/public/css/sass/commons/_colors.scss @@ -1,62 +1,98 @@ -$black: #000; -$grey: #6f6f6f; $white: white; -$grey1: #788190; -$grey2: #aebdcd; -$grey3: #d9e0e8; -$grey4: #eaebee; -$grey5: #f5f6f7; -$grey6: #666666; -$grey7: #9e9e9e; -$grey8: #d7d8db; -$grey9: #f3f3f3; - -$black100: rgba(26, 26, 41, 0.07); -$orange600: rgba(235, 191, 71, 1); -$blue800: rgba(42, 140, 252, 1); - -$darkBlue: #002b5a; -$darkBlueHover: #00254f; -$darkBlueTransparent: #d9e0e8; - -$linkBlue: #4184c4; -$linkBlueHover: #3174b4; -$linkBlueActive: #3174b4; -$linkBlueTransparent: #86aacd; - -$translatedBlue: #0099cc; -$translatedBlueHover: #0889b3; -$translatedBlueActive: #0889b3; -$translatedBlueTransparent: #63c3e3; -$transparentBlue: #e4f2fb; - -$approvedGreen: #2fb177; -$approvedGreenHover: #1c9f64; -$approvedGreenTransparent: #80d5af; - -$approved2Green: #9352c1; -$approved2GreenHover: #7a3ca6; -$approved2GreenTransparent: #b58dd2; - -$rebuttedRed: #ff8734; -$rebuttedRedHover: #e9511f; -$rebuttedRedTransparent: #ffaa8e; - -$greenDefault: #1fbd1f; -$greenDefaultHover: #1ba61b; -$greenDefaultTransparent: #7cc576; -$greenDefaultTransparent2: #d1e0d1; -$red800: rgba(239, 71, 64, 1); - -$redDefault: #e02020; -$redDefaultHover: #d31d1d; -$redDefaultTransparent: #ffc8ca; - -$orangeDefault: #ffcc01; -$orangeDefaultHover: #efbf00; -$orangeDefaultTransparent: #fee47a; -$orangeDefaultTransparent2: #fffed8; - -$warning: #f2711c; -$warningHover: #df681a; \ No newline at end of file +$black: #000; +$black100: rgba(#1A1A29, 0.07); + + +// Grey scale (lightest → darkest) +$grey50: #f5f6f7; +$grey75: #f3f3f3; +$grey100: #eaebee; +$grey150: #d9e0e8; +$grey200: #d7d8db; +$grey300: #aebdcd; +$grey400: #9e9e9e; +$grey500: #788190; +$grey600: #6f6f6f; +$grey700: #666666; +$grey800: #84848C; +$grey1300: #29292D; + + +// Orange scale (lightest → darkest) +$orange50: #fffed8; +$orange100: #fee47a; +$orange200: #ffcc01; +$orange300: #ebbf47; +$orange400: #efbf00; +$orange500: #ffaa8e; +$orange600: #ff8734; +$orange700: #f2711c; +$orange800: #df681a; +$orange900: #e9511f; + +// Red scale (lightest → darkest) +$red100: #ffc8ca; +$red400: #ef4740; +$red500: #e02020; +$red600: #d31d1d; + +// Blue scale (lightest → darkest) +$blue50: #e4f2fb; +$blue200: #63c3e3; +$blue300: #86aacd; +$blue400: #2a8cfc; +$blue500: #0099cc; //Translated blue +$blue600: #0889b3; +$blue700: #4184c4; +$blue800: #3174b4; +$blue900: #002b5a; +$blue950: #00254f; + +// Purple scale (lightest → darkest) +$purple200: #b58dd2; +$purple500: #9352c1; +$purple1000: #7E22CE; + +// Green scale (lightest → darkest) +$green50: #d1e0d1; +$green200: #80d5af; +$green300: #7cc576; +$green400: #4ADE80; +$green500: #1fbd1f; +$green600: #1c9f64; +$green700: #1ba61b; +$green800: #22C55E; +$green1000: #15803D; + +// Color variables for translation status +$transparentBlue: $blue50; +$translatedBlueTransparent: $blue200; +$linkBlueTransparent: $blue300; +$translatedBlue: $blue500; +$translatedBlueHover : $blue600; +$linkBlue: $blue700; +$linkBlueHover : $blue800; +$darkBlue:$blue900; +$darkBlueHover:$blue950; + +$greenDefaultTransparent2: $green50; +$approvedGreenTransparent:$green200; +$greenDefaultTransparent:$green300; +$approvedGreen:$green800; +$greenDefault:$green500; +$approvedGreenHover: $green600; +$greenDefaultHover:$green700; + +$approved2GreenTransparent: $purple200; +$approved2Green: $purple500; +$approved2GreenHover:$purple1000; + +$warning: $orange700; +$warningHover:$orange800; +$rebuttedRedTransparent: $orange500; +$rebuttedRed:$orange600; + +$redDefaultTransparent:$red100; +$redDefault: $red500; +$redDefaultHover:$red600; \ No newline at end of file diff --git a/public/css/sass/commons/_date-picker-translator.scss b/public/css/sass/commons/_date-picker-translator.scss index 22e62c463d..3af6ce0a97 100644 --- a/public/css/sass/commons/_date-picker-translator.scss +++ b/public/css/sass/commons/_date-picker-translator.scss @@ -4,30 +4,30 @@ } .xdsoft_datetimepicker .xdsoft_calendar td.xdsoft_today { - color: colors.$translatedBlue; + color: colors.$blue500; } .xdsoft_datetimepicker .xdsoft_calendar td.xdsoft_current { - background: colors.$translatedBlue; + background: colors.$blue500; box-shadow: none; - color: #ffffff; + color: colors.$white; } .xdsoft_datetimepicker .xdsoft_calendar td:hover { - color: #666 !important; - background: #d0d0d0 !important; + color: colors.$grey700 !important; + background: colors.$grey200 !important; box-shadow: none !important; } .xdsoft_datetimepicker .xdsoft_calendar td:active { - color: #ffffff !important; - background: colors.$translatedBlue !important; + color: colors.$white !important; + background: colors.$blue500 !important; box-shadow: none !important; } .xdsoft_datetimepicker .xdsoft_calendar td:focus { - color: #ffffff !important; - background: colors.$translatedBlue !important; + color: colors.$white !important; + background: colors.$blue500 !important; box-shadow: none !important; } @@ -36,28 +36,28 @@ .xdsoft_time_box > div > div.xdsoft_current { - background: colors.$translatedBlue; + background: colors.$blue500; box-shadow: none; } .xdsoft_datetimepicker .xdsoft_timepicker .xdsoft_time_box > div > div:hover { - color: #666 !important; - background: #d0d0d0 !important; + color: colors.$grey700 !important; + background: colors.$grey200 !important; box-shadow: none !important; } .xdsoft_datetimepicker .blue-gradient-button { - background: colors.$translatedBlue; + background: colors.$blue500; color: white; font-family: Calibri; - border: 1px solid #797979 !important; + border: 1px solid colors.$grey600 !important; padding: 4px; } .xdsoft_datetimepicker .blue-gradient-button:hover { - background: colors.$translatedBlue; - box-shadow: 0 0 0 #e0e0e0, 0 0 2px rgba(0, 0, 0, 0.12), + background: colors.$blue500; + box-shadow: 0 0 0 colors.$grey200, 0 0 2px rgba(0, 0, 0, 0.12), 0 2px 4px rgba(0, 0, 0, 0.24) !important; - color: #fff; - border: 1px solid #797979 !important; + color: colors.$white; + border: 1px solid colors.$grey600 !important; } diff --git a/public/css/sass/commons/_icons.scss b/public/css/sass/commons/_icons.scss index 4cb60fe899..a769ec5fa5 100755 --- a/public/css/sass/commons/_icons.scss +++ b/public/css/sass/commons/_icons.scss @@ -34,9 +34,6 @@ .icon-no-preview:before { content: '\ea8d'; } -.icon-quote-client:before { - content: '\ea89'; -} .icon-qr-matecat:before { content: '\e90a'; } @@ -211,12 +208,6 @@ .icon-tag2:before { content: '\e925'; } -.icon-link:before { - content: '\e926'; -} -.icon-link2:before { - content: '\e927'; -} .icon-cabinet:before { content: '\e928'; } diff --git a/public/css/sass/commons/_layout.scss b/public/css/sass/commons/_layout.scss new file mode 100644 index 0000000000..c625ce8c7a --- /dev/null +++ b/public/css/sass/commons/_layout.scss @@ -0,0 +1,65 @@ +// Breakpoints +$breakpoint-xs: 320px; +$breakpoint-sm: 480px; +$breakpoint-md: 768px; +$breakpoint-lg: 1024px; +$breakpoint-xl: 1600px; +$breakpoint-xxl: 1920px; + +// Grid widths +$grid-width-lg: 1280px; + +// Margins +$margin-xs: 16px; +$margin-sm: 16px; +$margin-md: 24px; +$margin-lg: 48px; +$margin-xl: 64px; +$margin-xxl: 64px; + +.layout__container { + width: 100%; + margin: 0 auto; + box-sizing: border-box; + // Mobile portrait (Xs) — > 320px: 4 columns, 16px margins, 100% width + @media (min-width: $breakpoint-xs) { + //padding-left: $margin-xs; + //padding-right: $margin-xs; + max-width: 100%; + } + + // Mobile landscape (Sm) — > 480px: 8 columns, 16px margins, 100% width + @media (min-width: $breakpoint-sm) { + //padding-left: $margin-sm; + //padding-right: $margin-sm; + max-width: 100%; + } + + // Tablet (Md) — > 768px: 8 columns, 24px margins, 100% width + @media (min-width: $breakpoint-md) { + //padding-left: $margin-md; + //padding-right: $margin-md; + max-width: 100%; + } + + // Small Desktop (Lg) — > 1024px: 12 columns, 48px margins, 1280px max + @media (min-width: $breakpoint-lg) { + //padding-left: $margin-lg; + //padding-right: $margin-lg; + max-width: $grid-width-lg ; + } + + // Desktop (Xl) — > 1600px: 12 columns, 64px margins, 1280px max + @media (min-width: $breakpoint-xl) { + //padding-left: $margin-xl; + //padding-right: $margin-xl; + max-width: $grid-width-lg ; + } + + // Large Desktop (Xxl) — > 1920px: 12 columns, 64px margins, 1280px max (REM scaling) + @media (min-width: $breakpoint-xxl) { + //padding-left: $margin-xxl; + //padding-right: $margin-xxl; + max-width: $grid-width-lg ; + } +} \ No newline at end of file diff --git a/public/css/sass/commons/_manage.scss b/public/css/sass/commons/_manage.scss index 2f42281533..f100b85503 100644 --- a/public/css/sass/commons/_manage.scss +++ b/public/css/sass/commons/_manage.scss @@ -1,4 +1,5 @@ @use 'colors'; +@use 'variables'; // rewrite semantic CSS html, @@ -8,7 +9,7 @@ body { body.manage { min-width: 1200px; font-family: Calibri, Arial, Helvetica, sans-serif; - background-color: colors.$grey5; + background-color: colors.$grey100; overflow-y: hidden; overflow-x: auto; font-size: 14px; @@ -84,13 +85,13 @@ div#manage-container { padding-bottom: 160px; .container { .ui.inverted.dimmer.more { - background-color: colors.$grey5; + background-color: colors.$grey50; } } .project { margin-bottom: 30px !important; - //border: 1px solid $grey2; + border-radius: variables.$border-radius-default; .project-title { display: flex !important; gap: 10px; @@ -108,17 +109,18 @@ div#manage-container { left: -33px; max-width: 540px; min-width: 0px; - line-height: 16px; - background-color: colors.$grey2; + line-height: 24px; + background-color: colors.$grey300; color: colors.$black; - height: 30px; + height: 38px; border-radius: 0 2px 2px 0; - display: inline-block; + display: flex; + align-items: center; margin-right: -33px; padding-left: 10px !important; } .project-header { - background-color: colors.$grey4; + background-color: colors.$grey100; padding-bottom: 10px !important; //border-bottom: 1px solid #ccc; margin-bottom: -25px; @@ -141,7 +143,7 @@ div#manage-container { display: inline-block; vertical-align: text-bottom; min-width: 72px; - color: #5a5a5a; + color: colors.$grey700; } .ui.form .field :disabled { opacity: 1 !important; @@ -174,7 +176,7 @@ div#manage-container { .ui.icon.input input { font-family: Calibri, Arial, Helvetica, sans-serif; padding-right: 2.67142857em !important; - box-shadow: inset 0 1px 3px #ddd; + box-shadow: inset 0 1px 3px colors.$grey200; } &.project-menu.ui.button { box-shadow: none; @@ -183,7 +185,7 @@ div#manage-container { margin-right: 8px; background-color: colors.$white; vertical-align: top; - border: 1px solid #bdbdbd; + border: 1px solid colors.$grey200; cursor: default; .text { border-radius: 15px; @@ -191,8 +193,8 @@ div#manage-container { color: black; transition: 0.3s ease; .ui.circular.label { - background-color: #cecece; - color: #888888; + background-color: colors.$grey200; + color: colors.$grey400; } } } @@ -231,16 +233,16 @@ div#manage-container { cursor: pointer; &:hover { - background-color: colors.$grey3; + background-color: colors.$grey150; } } } &:hover .text { - background-color: colors.$grey5 !important; + background-color: colors.$grey50 !important; } } &.project-assignee { - background-color: #ffffff !important; + background-color: colors.$white !important; vertical-align: top; /*height: 30px !important;*/ .text { @@ -249,7 +251,7 @@ div#manage-container { min-width: 30px; border-radius: 15px; padding: 3px 15px 3px 3px; - color: #000000; + color: colors.$black; transition: 0.3s ease; height: 30px; img { @@ -276,15 +278,15 @@ div#manage-container { padding: 15px; cursor: pointer; a { - color: colors.$translatedBlue; + color: colors.$blue500; } i { float: right; font-size: 18px; - color: colors.$translatedBlue; + color: colors.$blue500; } &:hover { - background-color: colors.$grey3; + background-color: colors.$grey150; } } .scrolling { @@ -302,22 +304,22 @@ div#manage-container { display: none; } &:hover .text { - background-color: #ffffff !important; + background-color: colors.$white !important; padding-right: 5px; padding-right: 30px; } &.disabled { - background-color: #f4f4f4 !important; - box-shadow: 0px 0px 1px #666 !important; + background-color: colors.$grey75 !important; + box-shadow: 0px 0px 1px colors.$grey700 !important; opacity: 1; &.text { - color: #666 !important; + color: colors.$grey700 !important; } } } &.project-not-assigned { - border: 1px solid #868686; + border: 1px solid colors.$grey600; padding: 0px 15px 0px 3px; trans\ition: 0.3s ease; color: rgba(0, 0, 0, 0.6); @@ -327,10 +329,10 @@ div#manage-container { transition: 0.3s ease; } &:hover { - border: 1px solid colors.$translatedBlue; - color: colors.$translatedBlue; + border: 1px solid colors.$blue500; + color: colors.$blue500; .icon-user22 { - color: colors.$translatedBlue; + color: colors.$blue500; } } .not-assigned { @@ -346,15 +348,15 @@ div#manage-container { padding: 15px; cursor: pointer; a { - color: colors.$translatedBlue; + color: colors.$blue500; } i { float: right; font-size: 18px; - color: colors.$translatedBlue; + color: colors.$blue500; } &:hover { - background-color: colors.$grey3; + background-color: colors.$grey150; } } } @@ -365,7 +367,7 @@ div#manage-container { &.project-assignee { .ui.cancel.label { padding: 4px; - background-color: #d6d6d6; + background-color: colors.$grey200; margin: 0px; border-radius: 15px; position: absolute; @@ -375,10 +377,10 @@ div#manage-container { visibility: hidden; i { font-size: 15px; - color: #ffffff; + color: colors.$white; } &:hover { - background-color: #cccccc !important; + background-color: colors.$grey200 !important; } } @@ -396,7 +398,7 @@ div#manage-container { } .project-body { - background-color: colors.$grey4; + background-color: colors.$grey100; .jobs { margin-top: 0px; @@ -405,7 +407,7 @@ div#manage-container { padding: 0 15px; margin-bottom: 15px; .job-header { - background-color: #ffffff !important; + background-color: colors.$white !important; padding: 0 0 !important; .split-merge { @@ -413,7 +415,7 @@ div#manage-container { .merge { font-family: Calibri, Arial, Helvetica, sans-serif; padding: 5px 17px; - border: 1px solid #797979; + border: 1px solid colors.$grey600; font-size: 16px; transition: 0.3s ease !important; } @@ -421,16 +423,15 @@ div#manage-container { } .job-body { .chunks { + border-radius: variables.$border-radius-default; + overflow: hidden; .chunk { display: grid; - grid-template-columns: - auto - 70px - 150px 120px 106px auto auto 1fr auto auto auto; + grid-template-columns: 20px 100px 150px 120px 106px 100px auto 180px 65px 40px; align-items: center; gap: 6px; transition: 0.3s ease; - background-color: #ffffff; + background-color: colors.$white; padding: 8px 10px !important; @media only screen and (max-width: 1200px) { @@ -438,16 +439,18 @@ div#manage-container { } .job-id { - color: #969696; + color: colors.$grey400; font-size: 12px; position: relative; } .source-target { font-weight: bold; position: relative; + display: flex; + gap: 2px; .source-box { float: left; - max-width: 60px; + max-width: 120px; min-width: 60px; white-space: nowrap; overflow: hidden; @@ -457,7 +460,7 @@ div#manage-container { .in-to { float: left; top: 4px; - color: #5a5a5a; + color: colors.$grey700; line-height: 26px; position: relative; font-size: 12px; @@ -467,7 +470,7 @@ div#manage-container { } .target-box { float: left; - width: 60px; + max-width: 120px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; @@ -481,55 +484,6 @@ div#manage-container { margin: unset !important; min-width: unset !important; } - .tm-job, - .activity-icon-single { - width: 30px; - height: 30px; - } - .job-activity-icons { - display: flex; - justify-content: center; - min-width: 110px; - gap: 5px; - - button.group-activity-icon { - height: 30px; - width: 30px; - i { - width: 30px; - } - } - .comments { - } - .group-activity-icons { - .item { - margin: 0; - padding: 1px !important; - a { - padding: 0; - width: 100%; - border-radius: 0px; - font-size: 15px; - font-weight: normal; - font-family: Calibri, Arial, Helvetica, sans-serif; - text-align: left; - margin: 0 15px 0 10px; - background: transparent !important; - box-shadow: none !important; - i { - margin-right: 10px !important; - } - } - } - } - } - .tm-job.job-activity-icons { - a { - i { - vertical-align: inherit; - } - } - } .outsource-job { display: inline-block; .translated-outsourced { @@ -554,28 +508,12 @@ div#manage-container { } } .job-to-translator { - display: inline-block; - vertical-align: text-bottom; - color: #969696; - max-width: 150px; - transition: 0.3s ease; - min-width: 0px; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - - @media only screen and (max-width: 1199px) and (min-width: 992px) { - width: fit-content; - &:hover { - } - } + width: 100%; + text-align: center; a { text-decoration: underline; font-weight: 700; } - &.not-assigned { - width: fit-content; - } } &:hover .job-to-translator { } @@ -601,7 +539,7 @@ div#manage-container { font-weight: 700; } .outsource-gmt-text { - color: #969696; + color: colors.$grey400; display: inherit; margin-left: 5px; font-size: 13px; @@ -620,20 +558,6 @@ div#manage-container { &:hover .translator .job-delivery { display: none; } - .outsource-delivery-container { - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - } - .job-delivery-date { - margin-left: 5px; - color: colors.$grey7; - - > :nth-child(2) { - font-weight: bold; - color: black; - } - } .item { margin-left: 10px; display: none; @@ -644,17 +568,17 @@ div#manage-container { } .ui.cancel { padding: 4px; - background-color: #d6d6d6; + background-color: colors.$grey200; margin-top: 3px; margin-bottom: 2px; position: relative; line-height: 0; right: 3px; font-size: 15px; - color: #ffffff; + color: colors.$white; } &:hover .ui.cancel { - background-color: #cccccc !important; + background-color: colors.$grey200 !important; } } &:hover .item { @@ -680,15 +604,6 @@ div#manage-container { text-decoration: none; } } - .open-translate { - font-family: Calibri, Arial, Helvetica, sans-serif; - padding: 6px 15px; - vertical-align: top; - font-size: 16px; - //border: 1px solid #797979; - border-radius: 2px; - float: right; - } .open-vendor { font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 16px; @@ -696,10 +611,10 @@ div#manage-container { border-radius: 2px; font-weight: bold; box-shadow: none !important; - color: #7eaf3e !important; + color: colors.$green300 !important; &:hover { box-shadow: - 0 0 0 #e0e0e0, + 0 0 0 colors.$grey200, 0 0 2px rgba(0, 0, 0, 0.12), 0 2px 4px rgba(0, 0, 0, 0.24) !important; } @@ -726,7 +641,7 @@ div#manage-container { display: flex; justify-content: end; align-items: center; - background: #fff; + background: colors.$white; color: colors.$black; font-weight: normal; border: none; // border: 1px solid #979797; @@ -746,11 +661,11 @@ div#manage-container { span { text-decoration: none; - color: colors.$grey; + color: colors.$grey600; } } span { - color: #000; + color: colors.$black; margin-left: 4px; line-height: 1.6; } @@ -769,7 +684,7 @@ div#manage-container { float: right; &:hover { box-shadow: - 0 0 0 #e0e0e0, + 0 0 0 colors.$grey200, 0 0 2px rgba(0, 0, 0, 0.12), 0 2px 4px rgba(0, 0, 0, 0.24) !important; } @@ -781,16 +696,14 @@ div#manage-container { } } .job-menu { - width: 28px !important; - height: 28px !important; &:hover { - background-color: rgba(colors.$grey8, 0.5) !important; + background-color: rgba(colors.$grey200, 0.5) !important; } } .chunk-download-progress { height: 2px; - background-color: #ffffff; + background-color: colors.$white; position: absolute; bottom: 0px; width: 100%; @@ -803,31 +716,36 @@ div#manage-container { left: 0; right: 0; bottom: 0; - background: #000000; + background: colors.$black; border-radius: 0.28571429rem; -webkit-animation: progress-active 1s ease infinite; animation: progress-active 1s ease infinite; } } &.updated-job { - background-color: #f9ffb5; + background-color: colors.$orange50; } } } } } } + .chunk-container { + border-radius: variables.$border-radius-default; + } .project-footer { padding: 0 30px 5px !important; text-align: right; - background-color: colors.$grey4; + background-color: colors.$grey100; + border-radius: 0 0 variables.$border-radius-default + variables.$border-radius-default; .activity-log { margin-top: -10px; margin-right: -15px; a { text-decoration: underline; - color: colors.$grey1; + color: colors.$grey500; font-size: 13px; &:hover { text-decoration: none; @@ -837,7 +755,7 @@ div#manage-container { .project-due-date { margin-top: -10px; margin-left: -15px; - color: colors.$grey1; + color: colors.$grey500; font-size: 13px; } } @@ -872,24 +790,10 @@ div#manage-container { } .message-create { - text-align: center; - display: block; + display: flex; font-size: 25px; - margin-top: 0px; - line-height: 40px; - p { - padding: 20px; - a { - text-align: center; - font-family: Calibri, Arial, Helvetica, sans-serif; - padding: 16px 25px; - vertical-align: top; - font-size: 20px; - border: 1px solid #797979; - border-radius: 2px; - margin: 10px; - } - } + justify-content: center; + gap: 15px; } } @@ -910,22 +814,15 @@ div#manage-container { margin-right: auto !important; transition: 0.3s ease; } - .outsource-delivery-container { - max-width: 210px; - } } -@media only screen and (min-width: 1500px) { +@media only screen and (min-width: 1501px) { .ui.container { width: 1280px !important; margin-left: auto !important; margin-right: auto !important; transition: 0.3s ease; } - - .outsource-delivery-container { - max-width: unset; - } } @media only screen and (max-width: 1360px) and (min-width: 992px) { @@ -978,10 +875,10 @@ div#manage-container { gap: 10px; .status-filter { display: inline-block; - background: #d8d8d8; + background: colors.$grey200; padding: 4px 5px 4px; border-radius: 2px; - color: #5d5d5d; + color: colors.$grey700; font-weight: 100; font-size: 12px; } @@ -995,84 +892,133 @@ div#manage-container { border-top: none; } -.project-team-dropdown, -.user-project-dropdown { - line-height: 1; - border-radius: 15px !important; - box-shadow: - 0 0 0 #e0e0e0, - 0 0 2px rgba(0, 0, 0, 0.12), - 0 2px 4px rgba(0, 0, 0, 0.24) !important; +.project-activity-icon button.project-team-dropdown { + font-size: 14px; + color: colors.$black; + padding: 5px 15px; + background-color: colors.$white; } -.project-menu-dropdown { - border-radius: 50% !important; - width: 28px !important; - height: 28px !important; - background-color: rgba(colors.$grey8, 0.5) !important; +.project-title-editing-name-mode { + > .label { + padding-top: 1px !important; + padding-right: 1px !important; + } - &:hover { - background-color: rgba(colors.$grey8, 1) !important; + .project-checkbox { + margin-top: 6px; } } -.project-activity-icon button.project-team-dropdown { - height: 30px; - font-size: 14px; - color: #000; - padding: 5px 15px; - background-color: #fff; +ul { + padding: 0; } -.user-project-dropdown-container button.user-project-dropdown { - height: 30px !important; - color: #000 !important; - font-size: 14px; +.project-container-checkbox-hidden { + opacity: 0; } -.project-container-button-edit-name { - width: 30px !important; - height: 30px !important; - line-height: 30px !important; -} +.projects-container { + .projects-container-title { + display: flex; + justify-content: space-between; + margin: 40px 0 16px; -.project-container-form-edit-name { - display: inline-block; + > :last-child { + display: flex; + gap: 16px; + color: colors.$grey700; - fieldset { - border: unset; - margin: 0; - padding: 0; - } + > span { + display: flex; + gap: 4px; + align-items: center; + } + } - input[type='text'] { - height: 28px; - min-width: 250px; - max-width: 400px; + .projects-container-legend-unconfirmed-quad, + .projects-container-legend-translated-quad, + .projects-container-legend-approved-quad, + .projects-container-legend-approved2-quad { + width: 12px; + height: 12px; + border-radius: 4px; + } - &:active, - &:focus { - box-shadow: unset; - border: 1px solid colors.$grey1; + .projects-container-legend-unconfirmed-quad { + background-color: colors.$black100; + border: 1px solid colors.$grey200; + } + .projects-container-legend-translated-quad { + background-color: colors.$blue500; + } + .projects-container-legend-approved-quad { + background-color: colors.$green800; + } + .projects-container-legend-approved2-quad { + background-color: colors.$purple500; } } -} -.project-title-editing-name-mode { - > .label { - padding-top: 1px !important; - padding-right: 1px !important; + &.projects-container--loading { + opacity: 0.5; } - .project-checkbox { - margin-top: 6px; + .spinner-loader-more-projects { + position: relative; + display: flex; + align-items: center; + justify-content: center; + opacity: 0; + transition: opacity 0.1s; + height: 120px; + + > h5 { + font-weight: normal; + } + + .spinner-loader-more-projects__loader-component { + position: absolute; + + > span { + white-space: nowrap; + } + } + } + + .spinner-loader-more-projects--visible { + opacity: 1; } } -ul { - padding: 0; +.projects-list { + display: flex; + flex-direction: column; + gap: 16px; } -.project-container-checkbox-hidden { - opacity: 0; +.filter-projects-container { + display: flex; + width: 60%; + max-width: 540px; + margin-left: auto; + margin-right: auto; + + > :first-child { + flex-grow: 1; + + > :first-child { + border-right: 1px solid colors.$grey150; + } + + input { + border-top-left-radius: 8px; + border-bottom-left-radius: 8px; + + &:active, + &:focus { + box-shadow: inset 0 0 0 1px colors.$blue600; + } + } + } } diff --git a/public/css/sass/commons/_nav-bar.scss b/public/css/sass/commons/_nav-bar.scss index 105633b5e6..476f1688c9 100644 --- a/public/css/sass/commons/_nav-bar.scss +++ b/public/css/sass/commons/_nav-bar.scss @@ -1,11 +1,11 @@ -@use "../commons/colors"; +@use '../commons/colors'; header { font-family: 'Calibri', 'Helvetica Neue', Arial, Helvetica, sans-serif; position: relative; width: 100%; z-index: 6; margin: 0; - background: #002b5c; + background: colors.$blue900; height: 60px; @media only screen and (max-width: 992px) { min-width: 992px; @@ -49,10 +49,10 @@ header { margin: 0; padding: 8px 16px; cursor: pointer; - color: colors.$translatedBlue; + color: colors.$blue500; &:hover { - background-color: #f3f3f3; + background-color: colors.$grey75; } i { @@ -60,7 +60,7 @@ header { font-size: 24px; margin-top: -3px; margin-right: -3px; - color: colors.$translatedBlue; + color: colors.$blue500; } } @@ -74,12 +74,12 @@ header { right: 10px; bottom: 20%; background-color: transparent; - color: colors.$translatedBlue; + color: colors.$blue500; font-size: 18px; padding-left: 1px; &:hover { - background-color: #dededc; + background-color: colors.$grey200; transition: 0.3s ease; } } @@ -133,7 +133,7 @@ header { box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.2); -moz-box-sizing: border-box; box-sizing: border-box; - color: colors.$translatedBlue; + color: colors.$blue500; display: -webkit-inline-box; display: -webkit-inline-flex; display: -ms-inline-flexbox; @@ -155,7 +155,7 @@ header { transition: 0.3s ease; cursor: pointer; background-color: transparent; - border: 2px solid colors.$translatedBlue; + border: 2px solid colors.$blue500; /*opacity: 0.8; &:hover { opacity: 1; @@ -195,18 +195,18 @@ header { padding: 0; width: 40px; /*&:hover { - border: 1px dashed $translatedBlue !important; + border: 1px dashed $blue500 !important; i { - color: $translatedBlue; + color: $blue500; } }*/ } .dropdown.select-org { - background-color: #ffffff; + background-color: colors.$white; border-radius: 30px; min-width: 105px; - color: #000000; + color: colors.$black; font-size: 14px; padding: 3px 15px; float: left; @@ -254,7 +254,7 @@ header { svg { path { - fill: #0099cc; + fill: colors.$blue500; } } } @@ -267,21 +267,21 @@ header { &.selected { .item-info { - color: #fff; + color: colors.$white; border-radius: 2px; - background: #002b5c; + background: colors.$blue900; a { svg { path { - fill: #fff; + fill: colors.$white; } } &:hover { svg { path { - fill: colors.$translatedBlue; + fill: colors.$blue500; } } } @@ -339,7 +339,7 @@ header { padding: 12px 8px !important; top: 45px !important; border-radius: 2px; - border: solid 1px #cdd4de; + border: solid 1px colors.$grey150; right: 8px !important; &::after { content: ''; @@ -347,7 +347,7 @@ header { height: 0; border-left: 6px solid transparent; border-right: 6px solid transparent; - border-bottom: 6px solid #ffffff; + border-bottom: 6px solid colors.$white; bottom: 100%; left: auto; right: 12%; @@ -361,8 +361,8 @@ header { font-size: 16px !important; &:hover { - background-color: #f2f5f7 !important; - color: #0055b8 !important; + background-color: colors.$grey50 !important; + color: colors.$blue400 !important; } &.selected { background-color: transparent !important; @@ -389,11 +389,10 @@ header { display: grid !important; grid-template-columns: auto auto auto auto; justify-content: right; - align-items: center; padding-right: 24px; .organization-name { - color: #fff; + color: colors.$white; font-size: 15px; font-family: 'Calibri', 'Helvetica Neue', Arial, Helvetica, sans-serif; font-weight: 600; @@ -422,15 +421,11 @@ header { } .logo { - position: relative; - float: left; border: 0; //margin-top: 5px; background: url(/public/img/logo_matecat_big_white.svg) 0px 0px no-repeat; width: 190px; height: 40px; - left: 20px; - top: 1px; } #menu-site { @@ -439,8 +434,8 @@ header { align-items: center; text-align: right; .btn { - background: #fff; - color: #002b5c; + background: colors.$white; + color: colors.$blue900; font-size: 16px; width: 140px; text-align: center; @@ -465,7 +460,7 @@ header { .cta-create-team { position: fixed !important; .ui.primary.button { - border: 1px solid #797979; + border: 1px solid colors.$grey600; float: right; border-radius: 2px; font-family: 'Calibri', 'Helvetica Neue', Arial, Helvetica, sans-serif; @@ -477,7 +472,7 @@ header { a { float: right; text-decoration: underline; - color: #39699a; + color: colors.$blue400; cursor: pointer; &:hover { text-decoration: none; @@ -490,4 +485,17 @@ header { margin: 0 !important; } - +.header-container { + display: flex; + height: 100%; + align-items: center; + padding: 0 40px 0 15px; + + .header-elements { + display: flex; + align-items: center; + flex-grow: 1; + justify-content: end; + gap: 16px; + } +} diff --git a/public/css/sass/commons/_outsource.scss b/public/css/sass/commons/_outsource.scss index a21a1fd434..c87144ab50 100644 --- a/public/css/sass/commons/_outsource.scss +++ b/public/css/sass/commons/_outsource.scss @@ -1,60 +1,21 @@ @use '../commons/colors'; +@use '../commons/variables'; + .after-open-outsource { - border-left: 2px solid colors.$translatedBlue; + border-left: 2px solid colors.$blue500; padding-left: 13px !important; } -.outsource-container { - padding: 0px !important; - margin-top: 30px !important; - margin-bottom: 30px !important; - width: 107%; - margin-left: -3% !important; - //margin-right: -2% !important; - //box-shadow: 0 1px 20px rgba(0, 0, 0, 0.67); - //overflow: hidden; - .outsource-header { - display: flex !important; - background-color: white; - gap: 20px; - align-items: center; - padding: 5px 35px 5px 40px !important; - z-index: 1; - .job-id { - color: #969696; - } - .source-target { - display: flex; - font-weight: bold; - .source-box, - .target-box { - width: unset !important; - max-width: unset !important; - font-size: 18px; - } +.outsource-container { + display: flex; + padding: 8px 24px 24px 56px; + flex-direction: column; + align-items: flex-end; + gap: 8px; + align-self: stretch; + border-bottom: 1px solid colors.$grey100; + background: colors.$grey50; - .in-to { - margin: 2px 0 0 6px; - } - } - .job-payable { - display: inline-block; - padding: 0 0 0 10px !important; - line-height: 30px; - position: relative; - text-decoration: none !important; - font-weight: 700; - font-size: 16px; - } - .project-subject { - display: inline-block; - line-height: 30px; - position: relative; - top: 2px; - font-size: 16px; - float: right; - } - } &.transitionOutsource-enter { height: 0; overflow: hidden; @@ -89,6 +50,7 @@ text-decoration: underline; font-weight: 700; cursor: pointer; + &:hover { text-decoration: none; } @@ -96,20 +58,23 @@ .select { padding: 9px 46px 9px 12px; - border-radius: 2px; + border-radius: variables.$border-radius-default; color: colors.$black; + background: rgba(colors.$grey600, 0.07); } .dropdown__list { padding: 0; + li.dropdown__option { height: 40px; } } .select-with-icon__wrapper { - height: 38px; + height: 40px; } + .select__dropdown-wrapper { width: 190%; } @@ -127,53 +92,34 @@ float: right; clear: both; position: relative; - width: 160px; - .gmt-select { - /*min-width: 107px !important; - width: auto; - background: transparent; - padding: 12px 8px 10px; - font-size: 14px !important; - .dropdown.icon { - padding: 10px 3px 0 0; - } - .text { - .gmt-description { - display: none; - } - } - .menu { - min-width: 330px; - height: 205px; - .item { - border-top: 1px solid #fafafa; - padding: 15px 5px 15px 10px !important; - white-space: normal; - word-wrap: normal; - .gmt-value { - display: inline-block; - margin-right: 5px; - } - .gmt-description { - display: inline-block; - } - } - }*/ - } + width: 250px; + } + .order-badge-container { + display: flex; + gap: 4px; + align-items: center; + } + .compact-view-header { + font-weight: 700; + font-size: 20px; + line-height: 28px; + margin-bottom: 8px ; } - .delivery-order, .container-reduced { .confirm-delivery-input { margin-top: 31px; + .back, .email-confirm, .input { display: inline-block; } + .back { float: left; margin-top: 12px; + a { i { position: relative; @@ -181,114 +127,120 @@ } } } + .email-confirm { padding-right: 15px; } + input { min-width: 235px; } } } + .confirm-delivery-box { - background: #daeddf; - padding: 9px 15px 3px; - text-align: right; + background: #d1e0d1; + padding: 8px; line-height: 20px; + border-radius: 8px; + margin-top: 8px; + .confirm-title { font-size: 18px; font-weight: 700; } + p { line-height: 16px; } } .assign-job-translator { - background-color: #d7d8dc; - padding: 10px 15px 35px; - width: 100%; + background-color: colors.$white; + display: flex; + padding: 16px; + flex-direction: column; + justify-content: flex-end; + align-items: flex-start; + gap: 8px; + align-self: stretch; + border-radius: 16px; + border: 1px solid colors.$grey100; .title { - display: inline-block; - padding: 15px 15px 15px 25px; - font-size: 20px; + font-size: 16px; font-weight: 700; - width: 25%; - vertical-align: top; - position: relative; - top: 24px; + line-height: 24px; } + .title-url { padding: 10px 0; width: 75%; display: inline-block; + .job-url { display: inline-block; + a { font-size: 16px; } } + .translator-assignee { width: 100%; + .ui.form { /*width: 100%;*/ .fields { margin: 0; + .field { font-size: 14px; + label { - padding-left: 15px; font-size: 14px; - font-weight: bold; + line-height: 20px; + margin-bottom: 8px; + font-weight: 400; } + input[type='text'], input[type='email'], span.select { - box-shadow: inset 0 1px 3px #ddd; - border: 1px solid #ccc; + box-shadow: inset 0 1px 3px colors.$grey200; + border: 1px solid colors.$grey200; font-family: Calibri, Arial, Helvetica, sans-serif; + border-radius: variables.$border-radius-default; + height: 40px; + &:focus { - border-color: #85b7d9; + border-color: colors.$blue300; } + &:active { - border-color: #85b7d9; + border-color: colors.$blue300; } } + &.send-job-box { - padding: 0 15px 0 10px; - padding-top: 22px; - width: 28%; - .send-job { - font-family: Calibri, Arial, Helvetica, sans-serif; - font-size: 16px; - border-radius: 2px; - padding: 10px 17px; - margin: 0; - float: right; - width: 97%; - min-width: 199px; - top: 1px; - position: relative; - } - } - &.translator-email { - width: 31%; - } - &.translator-delivery { - width: 21%; + align-content: flex-end; } + &.translator-time { width: 202px; + .selection.dropdown { width: 100%; min-width: 91px !important; - border: 1px solid #ccc; - box-shadow: inset 0 1px 3px #ddd; + border: 1px solid colors.$grey200; + box-shadow: inset 0 1px 3px colors.$grey200; font-size: 14px; + .menu { height: 205px; } } } + &.gmt { position: relative; width: 160px; @@ -300,11 +252,13 @@ } } } + .open-job-box { - background-color: colors.$grey2; + background-color: colors.$grey300; padding: 35px 30px 25px 40px; width: 100%; cursor: auto; + .title { display: inline-block; font-size: 26px; @@ -313,9 +267,11 @@ position: relative; top: -4px; } + .title-url { width: 88%; display: inline-block; + .job-url { display: inline-block; max-width: 80%; @@ -324,15 +280,16 @@ overflow: hidden; text-overflow: ellipsis; font-size: 15px; + a { font-size: 16px; } } + .button { font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 16px; //border: 1px solid #797979; - border-radius: 2px; padding: 9px 15px; margin: 0; float: right; @@ -348,6 +305,7 @@ z-index: 1; padding-left: 35px !important; height: 0; + .or { width: 25px; height: 25px; @@ -355,970 +313,614 @@ text-align: center; line-height: 25px; border-radius: 50%; - color: #ffffff; + color: colors.$white; position: absolute; top: -14px; left: 90px; } } - .background-outsource-vendor { - background: colors.$grey3; - width: 100%; - padding-bottom: 15px; - padding-top: 15px; - cursor: auto; - .outsource-not-available { - font-size: 20px; + .outsource-not-available { + font-size: 20px; + } + + .translated-loader { + position: absolute; + top: 50%; + left: 50%; + margin: 0; + text-align: center; + -webkit-transform: translateX(-50%) translateY(-50%); + transform: translateX(-50%) translateY(-50%); + + img { + width: 40px; } - .translated-loader { - position: absolute; - top: 50%; - left: 50%; - margin: 0; - text-align: center; - -webkit-transform: translateX(-50%) translateY(-50%); - transform: translateX(-50%) translateY(-50%); - img { + + .text-loader-outsource { + font-size: 28px; + margin-top: 10px; + font-weight: 700; + } + } + + .payment-service { + display: flex; + height: 32px; + align-items: center; + gap: 8px; + align-self: stretch; + justify-content: space-between; + + .fiducial-logo, svg { + color: colors.$grey400; + } + + .service-box { + display: flex; + } + + .project-management { + font-weight: 700; + } + + .fiducial-logo { + display: flex; + align-items: center; + gap: 4px; + } + } + + .payment-details-box { + background-color: colors.$white; + display: flex; + padding: 16px; + flex-direction: column; + align-items: flex-start; + align-self: stretch; + border: 1px solid colors.$grey100; + font: variables.$font-style-small; + border-radius: variables.$border-radius-big; + min-height: 150px; + position: relative; + .translator-job-details__title { + font-weight: 700; + margin-bottom: 8px; + } + + .translator-job-details { + display: flex; + flex-direction: row; + padding-bottom: 16px; + align-items: center; + align-self: stretch; + justify-content: space-between; + border-bottom: 1px solid colors.$grey100; + + .translator-details { + display: flex; + flex-direction: row; + gap: 12px; + width: 60%; + align-items: center; + border-right: 1px solid colors.$grey100; + + } + + .translator-avatar { + display: flex; width: 40px; + height: 40px; + padding: 8px; + justify-content: center; + align-items: center; + gap: 8px; + flex-shrink: 0; + border-radius: 1248.75px; + background: colors.$grey100; + color: colors.$grey800; + font-size: 15px; + } + + .translator-info { + display: flex; + flex-direction: column; } - .text-loader-outsource { - font-size: 28px; - margin-top: 10px; + + .translator-words { + color: colors.$blue500; + } + + .translator-words, .translator-feedback { + font: variables.$font-size-xsmall; + } + + + .source-target-outsource { + display: flex; + align-items: center; + font: variables.$font-style-base; font-weight: 700; } + + + .job-payment { + text-align: right; + color: colors.$grey400; + font: variables.$font-style-base; + } + + .job-price { + font-size: 20px; + font-weight: 700; + line-height: 28px; + } } - .outsource-to-vendor { - .payment-service { - padding: 5px 10px 15px; - .service-box { - display: inline-block; - padding: 0 10px 0 15px; - font-size: 26px; - font-weight: 700; - .service { - display: inline-block; - &.project-management { - } - &.translation, - &.revision { - margin-left: 8px; - } - } + + .revision-box { + display: flex; + padding: 8px 0; + justify-content: flex-end; + align-items: center; + align-self: stretch; + border-bottom: 1px solid colors.$grey100; + gap: 200px; + + .add-revision { + .revision-checkbox { + display: flex; + gap: 8px; + align-items: center; } - .fiducial-logo { - display: inline-block; - padding: 0; - vertical-align: text-bottom; - .translated-logo { - display: inline-block; - .logo-t { - width: 100px; - position: relative; - top: 6px; - padding: 0; - margin: 0 0 0 5px; - } - } + + input { + width: 16px; + height: 16px; + padding: 3px; + justify-content: center; + align-items: center; + gap: 8px; } } - .payment-details-box { - background-color: #ffffff; - padding: 15px; - position: relative; - min-height: 232px; - .translator-job-details { - padding-bottom: 10px; - .translator-details-box { - width: 38%; - border-right: 1px solid black; - display: inline-block; - vertical-align: middle; - padding: 0 0 0 10px; - .left, - .right { - display: inline-block; - margin: 0; - } - .left { - width: 42%; - .star { - position: relative; - left: -2px; - .icon { - &.active { - background: transparent !important; - color: #7eaf3e !important; - text-shadow: none !important; - } - } - } - } - .right { - float: right; - width: 58%; - text-align: right; - padding-right: 15px; - } - .translator-no-found { - p { - } - } - } - .job-details-box { - display: inline-block; - width: 44% !important; - vertical-align: middle; - padding: 0 0 0 15px; - position: relative; - .source-target-outsource { - display: inline-block; - width: 68%; - font-size: 18px; - .source-box { - display: inline-block; - } - .in-to { - display: inline-block; - font-size: 16px; - i { - position: relative; - top: 1px; - margin: 0; - font-weight: 100; - font-size: 13px; - color: #545353; - } - } - .target-box { - display: inline-block; - } - @media only screen and (max-width: 1199px) and (min-width: 992px) { - font-size: 16px; - .in-to { - font-size: 13px; - } - } - } - .job-payment { - display: inline-block; - width: 32%; - text-align: right; - padding-right: 28px; - .not-payable { - text-decoration: line-through; - font-size: 16px; - position: absolute; - top: -17px; - width: 30%; - padding-right: 28px; - } - .payable { - font-size: 18px; - } - } - } - .job-price { - display: inline-block; - vertical-align: middle; - width: 18%; - font-size: 20px; - text-align: center; - } + + .job-price { + font: variables.$font-style-base; + font-weight: 700; + } + } + + .delivery-order { + display: flex; + justify-content: space-between; + align-items: center; + align-self: stretch; + padding: 16px; + + .delivery-box { + display: flex; + flex-direction: column; + align-items: flex-start; + align-self: stretch; + gap: 4px; + + span.select { + box-shadow: inset 0 1px 3px colors.$grey200; + border: 1px solid colors.$grey200; + font-family: Calibri, Arial, Helvetica, sans-serif; } - .revision-box { - padding: 4px 0px; - background-color: colors.$grey2; - margin-bottom: 10px; - height: 28px; - .add-revision { - display: inline-block; - width: 82%; - text-align: right; - padding-right: 28px; - .checkbox { - } - } - .job-price { - display: inline-block; - font-size: 20px; - text-align: center; - width: 18%; + + .react-datepicker__input-container input { + height: 38px; + } + + label { + font: variables.$font-style-xsmall; + color: colors.$grey400; + } + + .delivery-date { + font-size: 20px; + font-style: normal; + font-weight: 700; + line-height: 28px; + } + + .delivery-options { + display: flex; + align-items: center; + gap: 16px; + align-self: stretch; + } + + .faster { + color: colors.$blue500; + text-decoration: underline; + + &:hover { + text-decoration: none; } } - .delivery-order { - width: 82%; + + .need-it-faster { + font-size: 16px; + cursor: pointer; + } + + .need-it-faster-message { + font-size: 15px; + font-weight: normal; + width: 600px; + margin-top: 9px; + } + + .errors-date { + font-weight: 100; + font-size: 14px; + display: flex; + margin-right: 6px; text-align: right; - display: inline-block; - vertical-align: top; - margin-top: 15px; - padding-right: 25px; - .delivery-box { - text-align: right; - display: inline-block; - font-size: 23px; - span.select { - box-shadow: inset 0 1px 3px #ddd; - border: 1px solid #ccc; - font-family: Calibri, Arial, Helvetica, sans-serif; - } - .react-datepicker__input-container input { - height: 38px; - } - label { - font-size: 16px; - display: inline-block; - vertical-align: middle; - font-weight: 100; - padding: 5px; - } - .atdd { - display: inline-block; - font-weight: 100; - } - .delivery-date { - display: inline-block; - padding: 5px; - } - .delivery-time { - display: inline-block; - padding: 5px 15px 5px 5px; - } + gap: 4px; - .need-it-faster { - font-size: 16px; - margin-top: 15px; - padding-right: 5px; - } - .need-it-faster-message { - font-size: 15px; - font-weight: normal; - width: 600px; - margin-top: 9px; - } - .errors-date { - font-weight: 100; - font-size: 14px; + &.past-date { + color: colors.$red500; + } + + &.too-far-date { + color: colors.$orange600; + + .tip { display: inline-block; - margin-right: 6px; - text-align: right; - &.past-date { - color: red; - } - &.too-far-date { - color: #ffa038; - .tip { - display: inline-block; - width: 5px; - margin-right: 20px; - i { - position: relative; - color: #a7a7a7; - font-size: 16px; - top: 2px; - } - } - } - &.generic-error { - color: red; + width: 5px; + margin-right: 20px; + + i { + position: relative; + color: colors.$grey400; + font-size: 16px; + top: 2px; } } } - @media only screen and (max-width: 1199px) and (min-width: 992px) { - width: 79%; - } - @media only screen and (max-width: 991px) and (min-width: 768px) { - width: 79%; + + &.generic-error { + color: red; } } - .need-it-faster-box { - margin-top: 0 !important; - .need-it-faster-close { - position: relative; - top: -29px; - left: 12px; - text-align: center; - padding: 5px 4px; - margin: 0; - width: 115px; - height: 115px; - border-radius: 15px; - background: white; - i { - margin: 0; - position: relative; - top: 2px; - font-size: 15px; - background: colors.$grey2; - color: #000000; - } - } - .delivery-box { - padding: 14px 15px; - text-align: left; - border: 1px solid colors.$grey2; - > div { - display: flex; - align-items: center; - } - .fields { - .field { - label { - font-weight: unset; - font-size: unset; - } - input[type='text'], - input[type='email'] { - box-shadow: inset 0 1px 3px #ddd; - border: 1px solid #ccc; - font-family: Calibri, Arial, Helvetica, sans-serif; - border-radius: 2px; - &:focus { - border-color: #85b7d9; - } - &:active { - border-color: #85b7d9; - } - } - &.input-time { - width: 130px; - .selection.dropdown { - width: 100%; - min-width: 101px !important; - border: 1px solid #ccc; - box-shadow: inset 0 1px 3px #ddd; - border-radius: 2px; - .text { - font-weight: 100 !important; - } - .menu { - height: 210px; - } - } - } - &.gmt { - position: relative; - width: 165px; - margin-right: 20px; - } - .get-price { - font-family: Calibri, Arial, Helvetica, sans-serif; - padding: 9px 11px; - vertical-align: top; - font-size: 18px; - border: 1px solid colors.$translatedBlue; - border-radius: 2px; - box-shadow: none !important; - background-color: #ffffff !important; - font-weight: 700; - margin-top: 33px; - &:hover { - text-decoration: none; - //box-shadow: 0 0 0 #e0e0e0, 0 0 2px rgba(0, 0, 0, 0.12), 0 2px 4px rgba(0, 0, 0, 0.24) !important; - border: 1px solid colors.$translatedBlue; - background-color: colors.$grey3; - } - &:focus { - box-shadow: none !important; - background-color: colors.$grey3 !important; - } - } - } - } - } + } + } + + .need-it-faster-box { + input { + height: 40px; + border-radius: variables.$border-radius-default; + padding: 9px 46px 9px 12px; + } + + .fields { + display: flex; + align-items: center; + gap: 8px; + + .field-buttons { + display: flex; + gap: 8px; + margin-top: 25px; } - .delivery-order-not-available { - margin-top: 24px; - width: 45%; - float: right; - .quote-not-available-message { - float: right; - text-align: right; - font-size: 20px; - margin-right: 57px; - line-height: 30px; + + .field { + display: flex; + flex-direction: column; + + label { + font-weight: unset; + font-size: unset; + margin-bottom: 4px; } - } - .order-box-outsource { - display: inline-block; - width: 18%; - min-width: 199px; - .order-box { - background-color: #a7d7916b; - height: 70px; - text-align: center; - margin-bottom: 5px; - display: flex; - flex-direction: column; - align-items: center; - .price-pw { - font-size: 16px; - color: colors.$black; - font-weight: 100; - cursor: pointer; + + input[type='text'], + input[type='email'] { + border: 1px solid colors.$grey200; + font-family: Calibri, Arial, Helvetica, sans-serif; + + &:focus { + border-color: colors.$blue300; } - .outsource-price { - font-size: 26px; - font-weight: 700; - padding: 17px 0 10px; + + &:active { + border-color: colors.$blue300; } - .content { - font-family: Calibri, Arial, Helvetica, sans-serif; - font-size: 15px; - a { - color: #000000; - font-weight: 100; - margin-left: 10px; - } - i { - margin-left: 5px; + } + + &.input-time { + width: 130px; + + .selection.dropdown { + width: 100%; + min-width: 101px !important; + border: 1px solid colors.$grey200; + box-shadow: inset 0 1px 3px colors.$grey200; + + .text { + font-weight: 100 !important; } + .menu { - height: 236px; - left: -10px; + height: 210px; } } } - @media only screen and (max-width: 1199px) and (min-width: 992px) { - width: 21%; - } - @media only screen and (max-width: 991px) and (min-width: 768px) { - width: 21%; + + &.gmt { + position: relative; + width: 250px; + margin-right: 20px; } } } - .easy-pay-box { - width: 100%; - padding: 5px 20px 15px; + + } + + .delivery-order-not-available { + margin-top: 24px; + width: 45%; + float: right; + + .quote-not-available-message { + float: right; text-align: right; - .easy-pay { + font-size: 20px; + margin-right: 57px; + line-height: 30px; + } + } + + .order-box-outsource { + display: flex; + width: 260px; + padding: 16px; + flex-direction: column; + justify-content: center; + align-items: flex-start; + gap: 8px; + border-radius: variables.$border-radius-big; + background-color: rgba(colors.$green800, 0.08); + + #accept-outsource-quote { + width: 100%; + } + + .order-box { + display: flex; + height: 28px; + justify-content: space-between; + align-items: center; + align-self: stretch; + + .price-pw { + font-size: 16px; + cursor: pointer; + } + + .outsource-price { + font-size: 28px; + line-height: 20px; font-weight: 700; - margin-bottom: 0; - font-size: 14px; - span { + color: colors.$green1000; + } + + .content { + font-family: Calibri, Arial, Helvetica, sans-serif; + font-size: 15px; + + a { + color: colors.$black; font-weight: 100; + margin-left: 10px; } - } - } - .customer-request { - .customer-box { - padding: 0 15px 15px; - position: relative; - overflow: hidden; - width: 55%; - .title-pointer { - h3 { - display: inline-block; - width: 50%; - padding-left: 30px; - margin-bottom: 5px; - } - .pointers { - /*display: inline-block; - text-align: right; - width: 50%;*/ - text-align: right; - .pointer { - width: 12px; - height: 12px; - background: #d5d8dc; - display: inline-block; - border-radius: 50%; - margin-right: 5px; - cursor: pointer; - transition: 0.3s ease; - &.active { - background: colors.$greenDefault; - } - } - } + + i { + margin-left: 5px; } - .slider-box { - min-height: 110px; - position: relative; - border: 1px solid #a8bbb2; - padding: 15px 0px; - .appendix { - display: inline-block; - width: 8%; - vertical-align: top; - font-size: 28px; - position: relative; - top: -3px; - color: #a8bbb2; - right: 13px; - background: #f1f3f2; - padding: 6px 2px; - text-align: center; - } - .customer-box-info { - width: 90%; - display: inline-block; - position: absolute; - opacity: 0; - &.fade-in { - transition: 1.5s; - opacity: 1; - } - .customer-text { - padding-bottom: 10px; - font-size: 14px; - line-height: 18px; - } - .customer-info { - width: 55%; - display: inline-block; - .customer-photo { - display: inline-block; - width: 30px; - height: 30px; - border-radius: 50%; - vertical-align: middle; - } - .customer-name { - display: inline-block; - margin-left: 10px; - } - .customer-role { - display: inline-block; - margin-left: 3px; - font-weight: 700; - } - } - .customer-corporate-logo { - display: inline-block; - width: 45%; - text-align: right; - vertical-align: middle; - img { - width: auto; - vertical-align: middle; - padding: 6px; - height: 40px; - } - .c-export { - height: 30px !important; - } - } - } + + .menu { + height: 236px; + left: -10px; } } - .request-box { - width: 45%; - .title-request { - position: absolute; - right: 30px; - bottom: 60px; - h3 { - margin-bottom: 5px; - padding-left: 30px; - } - } - .request-info-box { - color: #909894; - position: absolute; - bottom: 20px; - right: 30px; - .mobile-mail-box, - .account-box { - .item { - padding: 0; - .icon { - padding-right: 0; - margin-right: 5px; - } - .content { - padding-left: 0; - .header, - .description { - font-family: Calibri, Arial, Helvetica, sans-serif; - color: inherit; - } - a { - color: #000000 !important; - } - } - } - .call { - .icon { - margin-right: 0; - } - } - .send-email { - } - .open-chat { - i { - position: relative; - font-size: 16px; - } - .content { - .button { - font-family: Calibri, Arial, Helvetica, sans-serif; - border: 1px solid #c1c1c1; - background: #f3f3f3; - position: relative; - top: 5px; - width: 100%; - margin-right: 0; - padding: 9px 10px; - .sign { - width: 10px; - height: 10px; - display: inline-block; - vertical-align: baseline; - margin-right: 5px; - border-radius: 50%; - position: relative; - top: 1px; - &.online-item { - background-color: colors.$translatedBlue; - } - &.offline-item { - background-color: gray; - } - } - } - } - } + } + + } + } + + .easy-pay-box { + width: 100%; + padding: 5px 20px 15px; + text-align: right; + + .easy-pay { + font-weight: 700; + margin-bottom: 0; + font-size: 14px; + + span { + font-weight: 100; + } + } + } + + .customer-request { + display: flex; + padding: 16px; + justify-content: space-between; + align-items: flex-start; + align-self: stretch; + border-radius: 16px; + border: 1px solid colors.$grey100; + background: colors.$white; + + .customer-box { + display: flex; + flex-direction: column; + align-items: flex-start; + + .title-pointer { + align-self: flex-end; + + h3 { + display: inline-block; + width: 50%; + padding-left: 30px; + margin-bottom: 5px; + } + + .pointers { + /*display: inline-block; + text-align: right; + width: 50%;*/ + text-align: right; + + .pointer { + width: 12px; + height: 12px; + background: colors.$grey200; + display: inline-block; + border-radius: 50%; + margin-right: 5px; + cursor: pointer; + transition: 0.3s ease; + + &.active { + background: colors.$green500; } } } } - } - .outsource-to-vendor-reduced { - padding-top: 30px !important; - padding-left: 15px !important; - padding-right: 15px !important; - position: relative; - min-height: 145px; - .reduced-boxes { - .container-reduced { - padding: 0 10px; - width: 81%; + .slider-box { + display: flex; + width: 512px; + padding: 16px 16px 16px 48px; + flex-direction: column; + align-items: flex-start; + gap: 16px; + align-self: stretch; + border-radius: variables.$border-radius-default; + border: 1px solid colors.$grey100; + position: relative; + height: 135px; + @media (max-width: 1200px) { + width: 430px; + } + .quote { + position: absolute; + left: 8px; + top: 8px; + font-size: 64px; + line-height: 72px; + font-weight: 700; + color: colors.$grey700; + } + + .customer-box-info { + width: 90%; display: inline-block; - vertical-align: top; - .job-menu, - .open-translate { - display: none; + opacity: 0; + position: absolute; + padding-right: 16px; + + &.fade-in { + transition: 1.5s; + opacity: 1; } - .title-reduced { - font-size: 24px; - font-weight: 100; + + .customer-text { + padding-bottom: 10px; + font-size: 14px; + line-height: 18px; } - .payment-service { - display: inline-block; - width: 63%; - vertical-align: top; - position: relative; - top: 10px; - .service-box { + + .customer-info { + display: flex; + + .customer-photo { display: inline-block; - font-size: 22px; - font-weight: 700; - .service { - display: inline-block; - &.project-management { - } - &.translation { - margin-left: 6px; - margin-right: 6px; - } - &.revision { - margin-right: 6px; - } - } + width: 30px; + height: 30px; + border-radius: 50%; + vertical-align: middle; } - .fiducial-logo { + + .customer-name { display: inline-block; - img { - width: 100px; - position: relative; - top: 9px; - margin-left: 4px; - } - } - .view-more { - z-index: 1; - position: relative; - } - } - .delivery-order { - display: inline-block; - width: 37%; - text-align: right; - position: relative; - top: -15px; - .need-it-faster-box { - .delivery-box { - border: 1px solid colors.$grey2; - } + margin-left: 10px; } - .delivery-box { + + .customer-role { display: inline-block; - font-size: 18px; + margin-left: 3px; font-weight: 700; - > div { - display: flex; - align-items: center; - } - label { - padding: 5px; - font-size: 16px; - color: gray; - font-weight: 100; - display: flex; - } - .delivery-date, - .delivery-time { - display: inline-block; - padding: 5px; - } - .atdd { - display: inline-block; - font-weight: 100; - } - .delivery-time { - padding-right: 15px !important; - } - .gmt { - } - } - } - .delivery-order-not-available { - width: 40%; - float: right; - position: absolute; - right: -10px; - top: 20px; - .quote-not-available-message { - float: right; - text-align: right; - font-size: 20px; - margin-right: 57px; - line-height: 30px; } } - .errors-date { - font-weight: 100; - font-size: 14px; - display: inline-block; - margin-right: 6px; - text-align: right; - width: 100%; - position: relative; - top: -10px; - &.generic-error { - color: red; - } - } - .confirm-delivery-input { - text-align: right; - margin-top: 8px; - } - } - .order-box-outsource { - display: inline-block; - float: right; - text-align: center; - margin-top: -17px; - width: 18%; - min-width: 200px; - .order-box { - background-color: #a7d7916b; - padding: 25px 5px 15px; - margin-bottom: 5px; - display: flex; - flex-direction: column; - align-items: center; - .price-pw { - font-size: 16px; - color: colors.$black; - font-weight: 100; - cursor: pointer; - } - .outsource-price { - font-size: 28px; - font-weight: 700; - margin-bottom: 10px; - } - .content { - font-family: Calibri, Arial, Helvetica, sans-serif; - a { - color: #000000; - font-weight: 100; - font-size: 14px; - } - i { - margin-left: 5px !important; - } - .menu { - top: -5px; - left: -23px; - height: 95px; - } - } - } - .order-button-outsource { - .open-order, - .confirm-order { - width: 100%; - font-family: Calibri, Arial, Helvetica, sans-serif; - padding: 10px 22px; - vertical-align: top; - font-size: 16px; - border-radius: 2px; - margin: 0px; - } - } - } - .confirm-delivery-box { - text-align: right; - display: inline-block; - width: 100%; - margin-top: 10px; - } - @media only screen and (max-width: 1199px) and (min-width: 992px) { - .container-reduced { - width: 79%; - .payment-service { - width: 60%; - top: 18px !important; - } - .delivery-order { - width: 35%; - top: -15px; - .delivery-box { - label { - padding: 5px; - font-size: 16px; - color: gray; - font-weight: 100; - display: grid; - } - .gmt { - position: relative; - top: 15px; - } - } - } - } - } - @media only screen and (max-width: 991px) and (min-width: 768px) { - .container-reduced { - width: 79%; - .payment-service { - width: 60%; - top: 18px !important; - } - .delivery-order { - width: 35%; - top: -15px; - .delivery-box { - label { - padding: 5px; - font-size: 16px; - color: gray; - font-weight: 100; - display: grid; - } - .gmt { - position: relative; - top: 15px; - } - } - } - } - } - @media only screen and (max-width: 767px) { - .container-reduced { - width: 79%; - .payment-service { - width: 60%; - top: 18px !important; + .customer-corporate-logo { + margin-left: auto; + + img { + width: auto; + height: 20px; } - .delivery-order { - width: 35%; - top: -15px; - .delivery-box { - label { - padding: 5px; - font-size: 16px; - color: gray; - font-weight: 100; - display: grid; - } - .gmt { - position: relative; - top: 15px; - } - } + + .c-export { + height: 15px !important; } } } } } - &.compact-background { - background: #ffffff; - padding-bottom: 25px; - padding-top: 25px; - } - } - .order-button-outsource { - margin: 0; - .open-order, - .confirm-order { - font-family: Calibri, Arial, Helvetica, sans-serif; - padding: 10px; - margin: 0; - font-size: 18px; - border-radius: 2px; - width: 100%; - } - .open-outsourced { - font-family: Calibri, Arial, Helvetica, sans-serif; - padding: 11px 0 !important; - vertical-align: top; - font-size: 16px; - border-radius: 2px; - width: 100%; - float: right; - margin-right: 0 !important; - &:hover { - box-shadow: - 0 0 0 #e0e0e0, - 0 0 2px rgba(0, 0, 0, 0.12), - 0 2px 4px rgba(0, 0, 0, 0.24) !important; - } - &:focus { - box-shadow: none !important; - } - &:active { - box-shadow: none !important; + .request-box { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 8px; + + .title-request { + font-size: 20px; + line-height: 28px; + font-weight: 700; } - } - } - @media only screen and (min-width: 1200px) { - } + .request-info-box { + display: flex; + align-items: center; + gap: 16px; - @media only screen and (min-width: 1380px) { - } - @media only screen and (max-width: 1199px) and (min-width: 992px) { - .outsource-container { - width: 105%; - .container-reduced { - width: 79%; - } - } - } + .item { + display: flex; + align-items: center; + gap: 8px; + .icon { + padding-right: 0; + margin-right: 5px; + } - @media only screen and (max-width: 991px) and (min-width: 768px) { - } + .content { + padding-left: 0; - @media only screen and (max-width: 767px) { + .header, + .description { + font-family: Calibri, Arial, Helvetica, sans-serif; + color: inherit; + } + + a { + color: colors.$black !important; + } + } + } + + } + } } } diff --git a/public/css/sass/commons/_progress-mc-bar.scss b/public/css/sass/commons/_progress-mc-bar.scss index f8ce814736..1a869f0eda 100644 --- a/public/css/sass/commons/_progress-mc-bar.scss +++ b/public/css/sass/commons/_progress-mc-bar.scss @@ -1,4 +1,5 @@ -@use "../commons/colors"; +@use '../commons/colors'; +@use '../commons/variables'; #manage-container .progress-bar { height: 20px; top: 15px; @@ -23,11 +24,11 @@ //min-width: 120px; position: relative; .meter { - height: 12px; + height: 16px; width: 100%; float: left; margin: 0px 15px 0px 0 !important; - background-color: #d0d1d1; + background-color: colors.$grey200; overflow: hidden; border-radius: 10px; > div { @@ -52,19 +53,19 @@ } .translated-bar { - background-color: colors.$translatedBlue; + background-color: colors.$blue500; } .approved-bar { - background-color: colors.$approvedGreen; + background-color: colors.$green800; } .approved-bar-2nd-pass { - background-color: colors.$approved2Green; + background-color: colors.$purple500; } .warning-bar { - background-color: colors.$rebuttedRed; + background-color: colors.$orange600; } .draft-bar { - background-color: colors.$grey4; + background-color: colors.$grey100; } } } @@ -84,7 +85,7 @@ height: 8px; margin: -5px 0 0 0 !important; border: 0px; - border-radius: 8px; + border-radius: variables.$border-radius-default; a { height: 8px; border-radius: 0px; diff --git a/public/css/sass/commons/_shadows.scss b/public/css/sass/commons/_shadows.scss index 7ba6c2a818..782c6ab55c 100644 --- a/public/css/sass/commons/_shadows.scss +++ b/public/css/sass/commons/_shadows.scss @@ -1,9 +1,6 @@ +@use './colors'; //boxes .shadow-1 { - box-shadow: 0 0 0 #e0e0e0, 0 0 2px rgba(0, 0, 0, 0.12), + box-shadow: 0 0 0 colors.$grey200, 0 0 2px rgba(0, 0, 0, 0.12), 0 2px 4px rgba(0, 0, 0, 0.24) !important; } -//header example navbar -.shadow-2 { - box-shadow: 0 0 4px rgba(0, 0, 0, 0.14), 0 4px 8px rgba(0, 0, 0, 0.28); -} diff --git a/public/css/sass/commons/_sub-header.scss b/public/css/sass/commons/_sub-header.scss index 8644248114..6d036938ba 100644 --- a/public/css/sass/commons/_sub-header.scss +++ b/public/css/sass/commons/_sub-header.scss @@ -1,5 +1,5 @@ @use '../commons/colors'; - +@use '../commons/variables'; .sub-head { color: white; .ui.container.equal.width.grid { @@ -30,9 +30,9 @@ .search-state-filters { input.search-projects { height: 40px; - border-radius: 2px; - background-color: #fff; - color: #002b5c; + border-radius: variables.$border-radius-default; + background-color: colors.$white; + color: colors.$blue900; transition: 0.2s ease-in; font-size: 14px; max-width: 320px; @@ -40,24 +40,22 @@ padding: 12px 16px; box-shadow: none; border: none; - opacity: 0.4; &::placeholder { - color: #002b5c; + color: colors.$blue900; } &:focus { border: none !important; - opacity: 1; & + .dropdown { - background-color: #ffffff; + background-color: colors.$white; } } } .ui.dropdown { - background-color: #fff; - border-left: 1px solid #002b5c; + background-color: colors.$white; + border-left: 1px solid colors.$blue900; /*transition: 0.2s ease-in;*/ - color: #002b5c; + color: colors.$blue900; font-weight: 500; padding: 2px 16px 2px 8px; line-height: 1.21; @@ -67,11 +65,10 @@ display: grid; grid-template-columns: 36px auto; align-items: center; - opacity: 0.4; &:hover, &:active, &:focus { - opacity: 1; + //opacity: 1; } .text { svg { @@ -82,7 +79,7 @@ min-width: 144px; padding: 8px 8px 12px 8px; border-radius: 2px; - border: solid 1px #cdd4de; + border: solid 1px colors.$grey150; right: 0 !important; left: auto !important; box-shadow: 0 3px 5px 0 rgba(0, 0, 0, 0.2); @@ -93,7 +90,7 @@ .item { border-radius: 2px; - color: #002b5c; + color: colors.$blue900; font-size: 15px; padding: 8px !important; font-weight: normal; @@ -106,8 +103,8 @@ background-color: rgba(0, 0, 0, 0.03); } &.selected { - background-color: #002b5c; - color: #ffffff !important; + background-color: colors.$blue900; + color: colors.$white !important; } } } @@ -117,21 +114,15 @@ .filter-project-status-dropdown-trigger { gap: 0 !important; - border-radius: 0 !important; - opacity: 0.4; - margin-left: 1px; - - &:hover, - &[data-state='open'] { - opacity: 1; - } + border-radius: 0 variables.$border-radius-default + variables.$border-radius-default 0 !important; } .filter-project-status-dropdown { min-width: 140px; .dropdownmenu-item { &:not([data-disabled]).selected { - background-color: #00254f !important; + background-color: colors.$blue950 !important; color: white !important; } } diff --git a/public/css/sass/commons/_tooltip.scss b/public/css/sass/commons/_tooltip.scss index ced1221454..9c98646b4a 100644 --- a/public/css/sass/commons/_tooltip.scss +++ b/public/css/sass/commons/_tooltip.scss @@ -1,14 +1,15 @@ +@use './colors'; #powerTip { cursor: default; - background-color: #fff; + background-color: colors.$white; border-radius: 6px; - color: #000; + color: colors.$black; display: none; padding: 8px !important; position: absolute; white-space: nowrap; z-index: 2147483647; - border: 1px solid #d4d4d5; + border: 1px solid colors.$grey200; border-radius: 0.28571429rem; box-shadow: 0px 2px 4px 0px rgba(34, 36, 38, 0.12), 0px 2px 10px 0px rgba(34, 36, 38, 0.15); @@ -19,11 +20,11 @@ content: ''; width: 0.71428571em; height: 0.71428571em; - background: #ffffff; + background: colors.$white; -webkit-transform: rotate(45deg); transform: rotate(45deg); z-index: 2; - box-shadow: -1px -1px 0px 0px #d4d4d5; + box-shadow: -1px -1px 0px 0px colors.$grey200; top: -4px; } diff --git a/public/css/sass/commons/_typography.scss b/public/css/sass/commons/_typography.scss index cd3833d0e4..11ad54577b 100644 --- a/public/css/sass/commons/_typography.scss +++ b/public/css/sass/commons/_typography.scss @@ -1,32 +1,28 @@ -h1, -h2, -h3, -h4, -h5 { - line-height: 1.28571429em; - font-weight: bold; - padding: 0em; -} +@use './variables'; h1 { - min-height: 1rem; - font-size: 2rem; + margin: 0; + font: variables.$font-style-heading1; } - h2 { - font-size: 1.71428571rem; + margin: 0; + font: variables.$font-style-heading2; } - h3 { - font-size: 1.28571429rem; + margin: 0; + font: variables.$font-style-heading3; } - h4 { - font-size: 1.07142857rem; + margin: 0; + font: variables.$font-style-heading4; } - h5 { - font-size: 1rem; + margin: 0; + font: variables.$font-style-heading5; +} +h6 { + margin: 0; + font: variables.$font-style-heading6; } h1:first-child, @@ -34,7 +30,7 @@ h2:first-child, h3:first-child, h4:first-child, h5:first-child { - margin-top: 0em; + margin-top: 0; } h1:last-child, @@ -42,14 +38,14 @@ h2:last-child, h3:last-child, h4:last-child, h5:last-child { - margin-bottom: 0em; + margin-bottom: 0; } p { margin: 0 0 16px 0; - line-height: 1.4285em; + line-height: 23px; &:last-child { - margin-bottom: 0em; + margin-bottom: 0; } } @@ -63,7 +59,7 @@ body ::-webkit-scrollbar { body ::-webkit-scrollbar-track { background: rgba(0, 0, 0, 0.1); - border-radius: 0px; + border-radius: 0; } body ::-webkit-scrollbar-thumb { diff --git a/public/css/sass/commons/_variables.scss b/public/css/sass/commons/_variables.scss index 369d44c0d4..6c04bda804 100644 --- a/public/css/sass/commons/_variables.scss +++ b/public/css/sass/commons/_variables.scss @@ -1,8 +1,36 @@ -$approved-color: #639d5e; -$translated-color: #0798bc; -$rejected-color: #b02429; -$disabled-color: #ebebeb; -$disabled-border-color: #b3b3b3; +@use 'sass:list'; + +// Typography: +$font-family: Calibri, Arial, Helvetica, sans-serif; + +$font-weight-regular: 400; +$font-weight-medium: 500; +$font-weight-bold: 700; + +$font-size-big: 18px; +$font-size-base: 16px; +$font-size-small: 14px; +$font-size-xsmall: 12px; + +$line-height-big: 26px; +$line-height-base: 24px; +$line-height-small: 20px; +$line-height-xsmall: 16px; + +$font-style-big: $font-weight-regular list.slash($font-size-big, $line-height-big) $font-family; //500 18/26 Calibri, Arial, Helvetica, sans-serif +$font-style-base: $font-weight-regular list.slash($font-size-base, $line-height-base) $font-family; //500 16/24 Calibri, Arial, Helvetica, sans-serif +$font-style-small: $font-weight-regular list.slash($font-size-small, $line-height-small) $font-family; //400 14/20 Calibri, Arial, Helvetica, sans-serif +$font-style-xsmall: $font-weight-regular list.slash($font-size-xsmall, $line-height-xsmall) $font-family; //400 12/16 Calibri, Arial, Helvetica, sans-serif + +$font-style-heading1: $font-weight-bold 68px/80px $font-family; +$font-style-heading2: $font-weight-bold 48px/56px $font-family; +$font-style-heading3: $font-weight-bold 34px/40px $font-family; +$font-style-heading4: $font-weight-bold 24px/28px $font-family; +$font-style-heading5: $font-weight-bold 20px/24px $font-family; +$font-style-heading6: $font-weight-bold list.slash($font-size-base, $line-height-base) $font-family; + +$border-radius-default: 8px; +$border-radius-big: 16px; /******* Notifications ***********/ @@ -10,10 +38,10 @@ $notifications-width: 400px; $notificationShadowOpacity: 0.9; -$notification-success: #5ea400; -$notification-error: #ec3d3d; -$notification-warning: #ebad1a; -$notification-info: #369cc7; +$notification-success: #11C38F; +$notification-error: #ED655C ; +$notification-warning: #D9943E; +$notification-info: #60A9F6; @mixin box-sizing($boxsizing) { -webkit-box-sizing: $boxsizing; diff --git a/public/css/sass/components/Analyze/JobAnalyze.scss b/public/css/sass/components/Analyze/JobAnalyze.scss index 3ff00e3621..d9d46f81e3 100644 --- a/public/css/sass/components/Analyze/JobAnalyze.scss +++ b/public/css/sass/components/Analyze/JobAnalyze.scss @@ -1,36 +1,33 @@ -@use '../../commons/_colors'; - +@use '../../commons/colors'; +@use '../../commons/variables'; .job-analyze-header { - background-color: colors.$grey2; display: flex; - height: 32px; + height: 40px; align-items: center; - width: 100%; - justify-content: space-between; - font-size: 16px; - .job-analyze-header_left { - display: flex; - align-items: center; - gap: 16px; + align-self: stretch; + background: colors.$grey100; + font: variables.$font-style-small; + padding: 0 24px; + gap: 4px; + .job-analyze-header__id { + color: colors.$grey700; + font: variables.$font-style-xsmall; + min-width: 80px; } - .job-analyze-languages, - .job-analyze-header_right { - span { - font-weight: 700; - line-height: 16px; - } - } - .job-analyze-languages { + .job-analyze-header__languages { display: flex; align-items: center; - gap: 2px; + gap: 4px; + font-weight: 700; + } + .job-analyze-header__words { + color: colors.$blue500; + margin-left: auto; + font-weight: 700; } } .chunks-analyze { - padding: 0 0 16px 0; - padding-left: 0 !important; - padding-right: 0 !important; width: 100%; background-color: colors.$white; } @@ -41,10 +38,9 @@ 80px, 100px ); - grid-template-rows: 125px; - padding: 0 !important; - border-bottom: 1px solid colors.$grey3; - background-color: colors.$grey4; + grid-template-rows: 68px; + background-color: colors.$grey50; + font: variables.$font-style-xsmall; &.mtqe { grid-template-columns: minmax(100px, 150px) repeat(8, 1fr) minmax(80px, 100px); } @@ -53,9 +49,8 @@ flex-direction: column; height: 100%; text-align: right; - border-left: 1px solid colors.$grey3; min-width: 46px; - font-size: 16px; + color: colors.$grey400; &:first-child { border-left: none; > div { @@ -64,8 +59,7 @@ } :first-child { height: 85px; - border-bottom: 1px solid colors.$grey3; - font-weight: bold; + color: colors.$black; } > div { height: 32px; @@ -82,13 +76,13 @@ flex-direction: column; height: 100%; text-align: right; - color: colors.$grey; - background-color: colors.$grey5; + color: colors.$grey400; padding-right: 6px; - font-size: 16px; - :first-child { + border-right: 1px solid colors.$grey100; + :first-child { height: 85px; font-weight: normal; + color: colors.$grey400; } > div { height: 32px; @@ -99,8 +93,9 @@ display: flex; justify-content: flex-end; font-weight: 700; - font-size: 20px; - text-align: center; + text-align: right; + align-items: flex-end; + padding-right: 2px; > div { justify-content: center; border-bottom: none; @@ -112,23 +107,22 @@ .chunk-analyze-container { width: 100%; padding: 0 !important; + font: variables.$font-style-xsmall; .chunk-analyze-info { display: grid; grid-template-columns: minmax(100px, 150px) repeat(11, 1fr) minmax( 80px, 100px ); - padding-top: 16px; background-color: colors.$white; position: relative; - font-size: 16px; &.mtqe { grid-template-columns: minmax(100px, 150px) repeat(8, 1fr) minmax(80px, 100px); } .chunk-analyze-info-background { position: absolute; width: 86%; - background: colors.$grey; + background: colors.$grey600; height: 24px; right: 10px; top: 40px; @@ -136,8 +130,7 @@ border-radius: 4px 4px 0 0; } .chunk-analyze-info-header { - height: 48px; - background-color: #f5f6f7; + height: 56px; border-radius: 4px; display: flex; flex-direction: column; @@ -148,57 +141,53 @@ } .chunk-analyze-info-index { color: colors.$black !important; - font-weight: 700; - font-size: 14px; + font-weight: 700 !important; } .chunk-analyze-info-files { - color: colors.$black !important; + color: colors.$blue500 !important; display: flex; align-items: center; gap: 4px; text-decoration: underline; cursor: pointer; + svg { + color: colors.$blue500 !important; + } } :first-child { - color: colors.$grey; - font-size: 14px; + color: colors.$grey600; } > div { - height: 24px; + height: 28px; width: 100%; color: colors.$black; justify-content: space-between; display: flex; padding: 2px 8px; - font-size: 16px; + font-weight: 700; + align-items: center; } } .chunk-analyze-info-total { - > div { - justify-content: center !important; - } + background-color: colors.$grey50; :last-child { - font-size: 16px !important; font-weight: 700; } } > div { - border-right: 1px solid colors.$grey3; - &:last-child, - &:first-child { - border-right: none; - } > div:not(.chunk-analyze-info-header) { - height: 24px; + height: 28px; justify-content: right; display: flex; padding-right: 6px; line-height: 24px; + font-weight: 700; + align-items: center; } :first-child { - font-size: 14px; - color: colors.$grey; + font-weight: 400 !important; + color: colors.$grey600; } } } @@ -212,19 +201,18 @@ grid-template-rows: 24px; display: grid; padding: 0; - color: colors.$grey; + color: colors.$grey600; position: relative; &.mtqe { grid-template-columns: minmax(100px, 150px) repeat(8, 1fr) minmax(80px, 100px); } .chunk-file-detail-background { position: absolute; - width: 86%; - background: colors.$grey; + width: 100%; + background: colors.$grey50; height: 24px; - right: 10px; top: 0px; - opacity: 0.1; + z-index: 1; &.last { border-radius: 0 0 4px 4px; } @@ -234,15 +222,15 @@ justify-content: left; } > div { - border-right: 1px solid colors.$grey3; justify-content: right; display: flex; padding-right: 6px; line-height: 24px; + z-index: 2; } .chunk-file-detail-filename { - background-color: colors.$white; - padding-right: 0; + justify-content: space-between; + padding: 0 12px; svg { margin-top: 5px; } @@ -251,25 +239,17 @@ overflow: hidden; text-overflow: ellipsis; white-space: nowrap; - font-size: 12px; - width: 100px; - line-height: 24px; + max-width: 100px; + text-align: right; } > div { - display: flex; align-items: flex-start; - margin: 0 6px; - padding: 0 6px; width: 100%; gap: 4px; - background-color: colors.$grey4; cursor: default; } } - .chunk-file-detail-total { - justify-content: center; - border-right: none; - } + } .analyze-page .more-columns { grid-template-columns: minmax(100px, 150px) repeat(12, 1fr) minmax(80px,100px) !important; diff --git a/public/css/sass/components/CattolFooter.scss b/public/css/sass/components/CattolFooter.scss index f3ea2628cb..3506d1cd28 100644 --- a/public/css/sass/components/CattolFooter.scss +++ b/public/css/sass/components/CattolFooter.scss @@ -30,7 +30,7 @@ .grey-box { display: flex; flex-direction: column; - background-color: colors.$grey5; + background-color: colors.$grey50; border-radius: 4px; padding: 5px 10px; line-height: 1.2; @@ -40,7 +40,7 @@ } > :last-child { - color: colors.$grey6; + color: colors.$grey700; } .grey-box-row { diff --git a/public/css/sass/components/Footer.scss b/public/css/sass/components/Footer.scss index 11dd15a108..f1cf574a9d 100644 --- a/public/css/sass/components/Footer.scss +++ b/public/css/sass/components/Footer.scss @@ -1,7 +1,7 @@ @use "../commons/colors"; .normal-foo { - background-color: colors.$grey4; + background-color: colors.$grey100; min-width: 992px; width: 100%; .footer-body { @@ -26,13 +26,13 @@ background-size: cover; } .description { - color: colors.$grey1; + color: colors.$grey500; font-weight: 100; font-size: 12px; text-align: left; line-height: 14px; .link { - color: #00aee4; + color: colors.$blue500; text-decoration: underline; } } @@ -50,7 +50,7 @@ gap: 5px; a { margin: 0; - color: colors.$grey1; + color: colors.$grey500; text-align: left; font-size: 16px; font-weight: bold; @@ -58,12 +58,12 @@ display: flex; align-items: center; &.email-link { - color: #fff; - background-color: colors.$grey1; + color: colors.$white; + background-color: colors.$grey500; padding: 6px 24px; border-radius: 2px; &:hover { - background-color: colors.$grey6; + background-color: colors.$grey700; } } } diff --git a/public/css/sass/components/MarkAsCompleteButton.scss b/public/css/sass/components/MarkAsCompleteButton.scss deleted file mode 100644 index ab8764f6a2..0000000000 --- a/public/css/sass/components/MarkAsCompleteButton.scss +++ /dev/null @@ -1,39 +0,0 @@ -@use "../commons/colors"; -#markAsCompleteButton.isMarkableAsComplete { - background: colors.$translatedBlue; - color: #fff !important; - width: auto !important; - border-radius: 2px 0 0 2px; - padding: 0 5px !important; - text-transform: uppercase; - margin: 0 !important; -} -input#markAsCompleteButton[disabled] { - background: #d7d7d8; -} - -#markAsCompleteButton { - width: 30px !important; - height: 30px; - text-align: right; - background: transparent; - border: none; - - &.isMarkedComplete { - background-image: url('/public/img/icons/icon-mark-active.svg'); - background-size: cover; - } - &.isMarkableAsComplete { - opacity: 1; - padding: 0 !important; - border-radius: 0; - background: transparent url('/public/img/icons/icon-mark.svg'); - background-size: cover; - } - &.notMarkedComplete { - background: transparent url('/public/img/icons/icon-mark.svg'); - opacity: 0.7; - background-size: cover; - cursor: not-allowed; - } -} diff --git a/public/css/sass/components/MembersFilter.scss b/public/css/sass/components/MembersFilter.scss index 5e645ffb97..212833e43b 100644 --- a/public/css/sass/components/MembersFilter.scss +++ b/public/css/sass/components/MembersFilter.scss @@ -1,118 +1,142 @@ @use '../commons/colors'; -.members-filter-dropdown-container { +.members-filter-trigger-button { position: relative; - margin-top: 3px; - - .dropdown { - position: absolute; - left: 0; - visibility: hidden; - z-index: 1; - background-color: white; - margin-top: 5px; - padding: 5px; - min-width: 250px; - right: 0; - max-height: 450px; - overflow: auto; - opacity: 0; - transition: opacity 0.2s linear; - box-shadow: 0px 2px 3px 0px rgba(34, 36, 38, 0.15); - - &.open { - visibility: visible; - opacity: 1; - } - - ul { - padding: 0; - margin: 0; - list-style: none; - display: flex; - flex-direction: column; - - > li { - display: flex; - align-items: center; - gap: 5px; - cursor: pointer; - padding: 10px; - color: black; - - &:not(.item-filter) { - justify-content: space-between; - > :last-child { - color: colors.$translatedBlue; - font-weight: bold; - } - } + min-width: 180px; + max-width: 220px; + border-radius: 35px !important; + justify-content: start !important; + padding-left: 4px !important; + padding-right: 5px !important; + font-size: 14px !important; + color: black !important; + + &:disabled { + box-shadow: unset !important; + border: 1px solid colors.$grey200; + } - &:hover { - background-color: colors.$grey9; - } + > :first-child { + margin-left: 0 !important; + padding-left: 0 !important; + } - &.active { - background-color: colors.$darkBlueHover; - color: colors.$white; + > :last-child { + margin-left: auto; + margin-right: 6px; + } - &:not(.item-filter) { - > :last-child { - color: white; - } - } - } + > svg { + transition: transform 0.2s ease-in-out; + } - &.disabled { - cursor: default; - pointer-events: none; - opacity: 0.5; - } - } + &.members-filter-open { + > svg { + transform: rotate(180deg); } } - .trigger-button { - position: relative; - min-width: 180px; - max-width: 220px; - height: 35px !important; - border-radius: 35px !important; - justify-content: start !important; - padding-left: 0 !important; - font-size: 14px !important; - color: black !important; + .members-filter-user-full-name { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + } +} - &:disabled { - box-shadow: unset !important; - border: 1px solid colors.$grey8; - //color: $grey6 !important; - } +.members-filter-item-filter { + display: flex; + align-items: center; + gap: 5px; + cursor: pointer; + padding: 10px; + color: black; + + > :first-child { + font-size: 12px; + border: 2px solid colors.$blue500; + color: colors.$blue500; + border-radius: 100%; + width: 28px; + height: 28px; + display: flex; + text-align: center; + background-color: colors.$grey100; + padding: 6px 4px; + font-weight: bold; + margin-right: 0.25em; + line-height: 1; + } + &.members-filter-all { > :first-child { - margin-left: 3px !important; - padding-left: 0 !important; + font-size: 11px; } + } +} - > :last-child { - margin-left: auto; - margin-right: 6px; - } +.members-filter-popover-content { + z-index: 7; +} - > svg { - transition: transform 0.2s ease-in-out; - } +.members-filter-dropdown-content { + background-color: white; + padding: 5px; + min-width: 250px; + max-height: 450px; + overflow: auto; + box-shadow: 0px 2px 3px 0px rgba(34, 36, 38, 0.15); + + ul { + padding: 0; + margin: 0; + list-style: none; + display: flex; + flex-direction: column; + + > li { + display: flex; + align-items: center; + gap: 5px; + cursor: pointer; + padding: 10px; + + &:hover { + background-color: colors.$grey75; + } + + &.active { + background-color: colors.$blue950; + color: colors.$white; + + &:not(.members-filter-item-filter) { + > :last-child { + color: colors.$white; + } + } + } + + &:not(.members-filter-item-filter) { + justify-content: space-between; - &.open { - > svg { - transform: rotate(180deg); + > :last-child { + font-weight: bold; + color: colors.$blue500; + } } } + } - .user-full-name { - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; + .add-new-member { + border-bottom: 1px solid colors.$grey200; + margin-bottom: 10px; + text-transform: uppercase; + color: colors.$blue500; + font-weight: bold; + justify-content: space-between; + + > svg { + border: 1px solid colors.$blue500; + border-radius: 50%; } } @@ -135,37 +159,6 @@ .no-results { text-align: center; - color: #9e9e9e; - } - - .item-filter { - display: flex; - align-items: center; - gap: 5px; - cursor: pointer; - padding: 10px; - color: black; - - > :first-child { - font-size: 12px; - border: 2px solid colors.$translatedBlue; - color: colors.$translatedBlue; - border-radius: 100%; - width: 28px; - height: 28px; - display: flex; - text-align: center; - background-color: colors.$grey4; - padding: 6px 4px; - font-weight: bold; - margin-right: 0.25em; - line-height: 1; - } - - &.all { - > :first-child { - font-size: 11px; - } - } + color: colors.$grey400; } } diff --git a/public/css/sass/components/NotificationBox.scss b/public/css/sass/components/NotificationBox.scss index 60206414a6..dead58176d 100644 --- a/public/css/sass/components/NotificationBox.scss +++ b/public/css/sass/components/NotificationBox.scss @@ -1,171 +1,130 @@ @use '../commons/variables'; +@use '../commons/colors'; /******* Notifications ************/ +.notifications-wrapper-inside { + .translator-notification-sent { + font-weight: bold; + line-height: 28px; + span { + color: colors.$blue700; + } + } +} + +.notification-item { + display: flex; + justify-content: space-between; + width: 100%; + border-radius: 12px; + background-color: colors.$white; + padding: 16px; + box-shadow: 0 1px 20px rgba(colors.$grey700, 0.3); + opacity: 0; + @include variables.transition(0.3s ease-in-out); + + > :first-child { + display: flex; + gap: 12px; + } +} + .notifications-position { - font-family: inherit; position: fixed; width: variables.$notifications-width; + height: auto; padding: 0 10px 10px 10px; z-index: 99999999; @include variables.box-sizing(border-box); - height: auto; } .notifications-position-bl { - @extend .notifications-position; top: auto; bottom: 30px; left: 20px; right: auto; } .notifications-position-bc { - @extend .notifications-position; top: auto; bottom: 30px; margin: 0 auto; left: 50%; - margin-left: calc(-1 * (variables.$notifications-width / 2)); } .notifications-position-br { - @extend .notifications-position; top: auto; bottom: 30px; left: auto; right: 0px; } .notifications-position-tl { - @extend .notifications-position; top: 60px; bottom: auto; left: 0px; right: auto; } .notifications-position-tc { - @extend .notifications-position; top: 60px; bottom: auto; margin: 0 auto; left: 50%; - margin-left: calc(-1 * (variables.$notifications-width / 2)); } .notifications-position-tr { - @extend .notifications-position; top: 60px; bottom: auto; left: auto; } -.notification-type { - position: relative; - width: 100%; - text-align: left; - background-color: #fff; - @include variables.border-radius(2px); - font-size: 16px; - margin: 10px 0 0; - padding: 15px; - box-shadow: 0 1px 10px #666; - display: block; - @include variables.box-sizing(border-box); - opacity: 0; - @include variables.transition(0.3s ease-in-out); - .notification-message { - word-wrap: break-word; - } +.notification-item-icon { + display: flex; + align-items: center; + justify-content: center; + width: 24px; + height: 24px; + border-radius: 50%; } .notification-type-success { - @extend .notification-type; - border-top: 3px solid variables.$notification-success; -} + .notification-item-icon { + background-color: rgba(variables.$notification-success, 0.1); -.notification-type-error { - @extend .notification-type; - border-top: 3px solid variables.$notification-error; + svg { + color: variables.$notification-success; + } + } } -.notification-type-warning { - @extend .notification-type; - border-top: 3px solid variables.$notification-warning; -} +.notification-type-error { + .notification-item-icon { + background-color: rgba(variables.$notification-error, 0.1); -.notification-type-info { - @extend .notification-type; - border-top: 3px solid variables.$notification-info; -} -.notification-message { - .warning-call-to { - text-transform: uppercase; - margin: 5px 0 0; - text-align: right; - a { - text-decoration: underline; - color: #4183c4; - font-weight: 700; - &:hover { - text-decoration: none; - } + svg { + color: variables.$notification-error; + transform: rotate(180deg); } } -} -.notification-close-button { - font-size: 14px; - position: absolute; - top: 10px; - right: 10px; - line-height: 14px; - background-color: #333; - color: #ffffff; - border-radius: 50%; - width: 14px; - height: 14px; - font-weight: bold; - text-align: center; - cursor: pointer; - &:hover { - background-color: #666; + .notification-item-content > :first-child { + color: variables.$notification-error; } } -.notification-title { - font-size: 18px; - margin: 0 0 7px 0; - padding: 0; - font-weight: bold; -} - -.notification-title-success { - @extend .notification-title; - color: variables.$notification-success; -} -.notification-title-error { - @extend .notification-title; - color: variables.$notification-error; -} -.notification-title-warning { - @extend .notification-title; - color: variables.$notification-warning; -} -.notification-title-info { - @extend .notification-title; - color: variables.$notification-info; -} +.notification-type-warning { + .notification-item-icon { + background-color: rgba(variables.$notification-warning, 0.1); -.notification-message{ - a { - color: variables.$notification-info; - } - a.bold { - font-weight: bold; + svg { + color: variables.$notification-warning; + transform: rotate(180deg); + } } + } -.notifications-wrapper-inside { - .translator-notification-sent { - font-weight: bold; - line-height: 28px; - span { - color: #4183c4; +.notification-type-info { + .notification-item-icon { + background-color: rgba(variables.$notification-info, 0.1); + + svg { + color: variables.$notification-info; } } } diff --git a/public/css/sass/components/ProjectBulkActions.scss b/public/css/sass/components/ProjectBulkActions.scss index 9e26309504..d0fc7e6e7a 100644 --- a/public/css/sass/components/ProjectBulkActions.scss +++ b/public/css/sass/components/ProjectBulkActions.scss @@ -3,15 +3,8 @@ .project-bulk-actions-background { position: fixed; z-index: 3; - top: 80px; + top: 145px; margin-left: -100px; - background: colors.$grey5; - background: linear-gradient( - 180deg, - rgba(colors.$grey5, 1) 0%, - rgba(colors.$grey5, 1) 84%, - rgba(colors.$grey5, 0) 100% - ); &.project-bulk-actions-background-hidden { display: none; @@ -24,7 +17,7 @@ padding: 5px; justify-content: center; align-items: center; - background-color: colors.$grey4; + background-color: colors.$white; border-radius: 24px; > div { @@ -39,7 +32,7 @@ width: 25px; height: 25px; font-size: 12px; - background-color: colors.$grey6; + background-color: colors.$grey700; border-radius: 50%; display: flex; align-items: center; @@ -49,11 +42,11 @@ } .jobs-selected-reached-limit { - background-color: colors.$orangeDefaultHover; + background-color: colors.$orange400; } > span:not(:first-of-type) { - color: colors.$grey6; + color: colors.$grey700; } > div { @@ -63,7 +56,7 @@ } .button-component-container:disabled { - color: colors.$grey7 !important; + color: colors.$grey400 !important; } } @@ -80,6 +73,10 @@ .bulk-actions-circle-button { border-radius: 50% !important; + + &:hover { + background-color: colors.$grey100 !important; + } } .project-bulk-spacer { @@ -88,6 +85,6 @@ width: 30px; height: 1px; display: block; - background: colors.$grey7; + background: colors.$grey400; } } diff --git a/public/css/sass/components/Projects/JobContainer.scss b/public/css/sass/components/Projects/JobContainer.scss new file mode 100644 index 0000000000..b81e02ec7f --- /dev/null +++ b/public/css/sass/components/Projects/JobContainer.scss @@ -0,0 +1,202 @@ +@use '../../commons/colors'; + +.job-container { + display: flex; + flex-direction: column; +} + +.job-container-grid { + display: grid; + grid-template-columns: + 20px 180px minmax(auto, 240px) + 140px 100px minmax(0, 1fr) auto auto auto; + align-items: center; + padding: 16px 24px; + gap: 16px; + border-bottom: 1px solid colors.$grey100; + + .chunks-job-container & { + border-bottom: unset; + } + + .job-container-id { + display: flex; + flex-direction: column; + color: colors.$grey700; + } +} + +.chunks-job-container { + display: flex; + flex-direction: column; + padding: 16px 24px; + gap: 16px; + border-bottom: 1px solid colors.$grey100; + + .chunks-job-container-line { + display: flex; + justify-content: space-between; + + .chunks-job-container-line-sx { + > :last-child { + display: flex; + } + } + + .chunks-job-container-line-sx, + .chunks-job-container-line-dx { + display: flex; + gap: 16px; + } + } + + .chunks-job-container-list { + padding-left: 8px; + } +} + +.chunk-job-container { + grid-template-columns: + 180px minmax(auto, 240px) + 140px 100px 1fr auto auto auto; + padding: 16px 0px 16px 24px; +} + +.job-container-grid, +.chunks-job-container { + .job-languages-code { + display: flex; + align-items: center; + gap: 4px; + color: colors.$black; + + svg { + color: colors.$grey400; + transform: rotate(270deg); + } + } +} + +.job-container-outsource { + display: flex; + justify-content: end; + align-items: center; + gap: 10px; +} + +.job-progress-bar-tooltip { + display: flex; + flex-direction: column; + + > div { + display: flex; + gap: 8px; + justify-content: space-between; + + > :first-child { + display: flex; + gap: 8px; + align-items: center; + } + } + + .job-progress-bar-unconfirmed-quad, + .job-progress-bar-translated-quad, + .job-progress-bar-approved-quad, + .job-progress-bar-approved2-quad { + width: 12px; + height: 12px; + border-radius: 4px; + } + + .job-progress-bar-unconfirmed-quad { + background-color: colors.$black100; + border: 1px solid colors.$grey200; + } + .job-progress-bar-translated-quad { + background-color: colors.$blue500; + } + .job-progress-bar-approved-quad { + background-color: colors.$green800; + } + .job-progress-bar-approved2-quad { + background-color: colors.$purple500; + } +} + +.job-activity-icons { + display: flex; + gap: 4px; + justify-content: center; + align-items: center; +} + +.job-container-button-weight-normal { + font-weight: normal !important; +} + +.job-container-words-button { + span { + color: colors.$grey400; + } +} + +.job-container-outsource-container { + display: flex; +} + +.job-container-outsource { + > div { + min-width: 0; + } +} + +.job-container-outsource-logo { + display: flex; + width: 100px; + + img { + width: 100px; + } +} + +.job-delivery-date { + display: flex; + min-width: 0; + align-items: center; + + > div { + white-space: nowrap; + display: block; + overflow: hidden; + } + + > span { + display: block; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + } +} + +.job-delivery-date-button-close { + flex-shrink: 0; + margin-left: 5px; +} + +@media only screen and (min-width: 1300px) { + .job-delivery-email { + max-width: 130px; + } + + .job-delivery-date { + > :nth-child(2) { + flex-shrink: 0; + } + } +} + +.job-delivery-email { + overflow: hidden; + text-overflow: ellipsis; +} diff --git a/public/css/sass/components/Projects/ProjectContainer.scss b/public/css/sass/components/Projects/ProjectContainer.scss new file mode 100644 index 0000000000..b276ac09f1 --- /dev/null +++ b/public/css/sass/components/Projects/ProjectContainer.scss @@ -0,0 +1,98 @@ +@use '../../commons/colors'; +@use '../../commons/variables'; + +.project-container { + display: flex; + flex-direction: column; + background-color: colors.$white; + border: 1px solid colors.$grey150; + border-radius: 18px; + overflow: hidden; +} + +.project-container-header { + display: flex; + justify-content: space-between; + padding: 7px 24px; + align-items: center; + align-self: stretch; + background-color: colors.$grey50; +} + +.project-container-header-sx, +.project-container-header-dx { + display: flex; + gap: 16px; + align-items: center; +} + +.project-container-header-dx { + gap: 8px; +} + +.project-container-header-name { + display: flex; + align-items: center; + gap: 2px; + + h6 { + font-weight: bold; + } + + &:has(> form) { + gap: 8px; + } +} + +.project-container-form-edit-name { + display: inline-block; + + fieldset { + border: unset; + margin: 0; + padding: 0; + } + + input[type='text'] { + height: 28px; + min-width: 250px; + max-width: 400px; + border-radius: variables.$border-radius-default; + &:active, + &:focus { + box-shadow: unset; + border: 1px solid colors.$grey500; + } + } +} + +.project-container-footer { + display: flex; + align-items: center; + padding: 10px 24px; + + > * { + color: colors.$grey700 !important; + font-size: 12px !important; + font-style: italic !important; + } + + button { + padding: 0 !important; + font-weight: normal !important; + } + + > :last-child { + margin-left: auto; + } +} + +.project-team-dropdown, +.user-project-dropdown { + border-radius: 999px !important; + font-weight: normal !important; +} + +.project-menu-dropdown { + border-radius: 50% !important; +} diff --git a/public/css/sass/components/ReviewExtendedPanel.scss b/public/css/sass/components/ReviewExtendedPanel.scss index 78cbc04a6d..eaee9728ba 100644 --- a/public/css/sass/components/ReviewExtendedPanel.scss +++ b/public/css/sass/components/ReviewExtendedPanel.scss @@ -23,14 +23,14 @@ input { .re-warning-not-added-issue { p { background: variables.$notification-error; - color: #fff; + color: colors.$white; padding: 5px 10px; a { - color: #fff; + color: colors.$white; font-weight: bolder; cursor: pointer; &:hover { - color: #fff; + color: colors.$white; text-decoration: underline; } } @@ -38,8 +38,8 @@ input { } .re-warning-selected-text-issue { p { - background: #ffeb3b; - color: #000; + background: colors.$orange200; + color: colors.$black; padding: 5px 10px; } } @@ -54,7 +54,7 @@ input { overflow-y: hidden; } .re-item-head { - border-bottom: 1px solid #f2f4f7; + border-bottom: 1px solid colors.$grey50; padding-top: 10px; margin-right: 1px; font-size: 16px; @@ -70,7 +70,7 @@ input { .re-item { &:hover, &.active { - background: colors.$grey5 !important; + background: colors.$grey50 !important; } .re-item-box { display: flex; @@ -97,6 +97,7 @@ input { .issue-activity-icon { .icon-buttons { display: flex; + gap: 4px; } } } @@ -120,28 +121,28 @@ input { } .re-comment-list { .re-comment { - background: #fff; + background: colors.$white; padding: 5px 10px; margin-bottom: 0; .re-revisor { - color: colors.$approvedGreen; + color: colors.$green800; } .re-revisor2 { - color: colors.$approved2Green; + color: colors.$purple500; } .re-translator { - color: colors.$translatedBlue; + color: colors.$blue500; } .re-comment-date { color: lightslategray; } .re-selected-text { - color: #000; + color: colors.$black; } } .re-highlighted { padding: 10px; - border-bottom: 1px solid #797979; + border-bottom: 1px solid colors.$grey600; } span.re-selected-text { @@ -158,7 +159,7 @@ input { display: flex; button { padding: 7px 10px; - background-color: #f2f4f7; + background-color: colors.$grey50; @media only screen and (max-width: 1450px) { padding: 7px 7px; } @@ -171,7 +172,7 @@ input { &:hover, &.active { - background-color: #cacbcd; + background-color: colors.$grey200; } } } @@ -200,20 +201,20 @@ input { } .re-item.issue-comments-open { transition: 0.3s ease; - background: #f2f4f7; + background: colors.$grey50; } .re-created { - background: colors.$grey3; + background: colors.$grey150; padding: 10px 10px 10px; margin-bottom: 0; .issues { .re-item-issue-value { - background: #ffffff; + background: colors.$white; } } } .re-to-create { - background: #ffffff; + background: colors.$white; .errors { max-height: 450px; .re-category-item { @@ -238,7 +239,7 @@ article { } .re-abb-issue { - background: #e5e9f1; + background: colors.$grey100; padding: 0 4px; margin-right: 5px; color: black; @@ -250,7 +251,7 @@ article { .re-open-view.re-issues { top: 0px; - border-top: 12px solid #fff; + border-top: 12px solid colors.$white; border-left: 14px solid transparent; filter: drop-shadow(-1px 0px 1px rgba(0, 0, 0, 0.2)); margin-left: -14px; @@ -259,13 +260,13 @@ article { border-top: 12px solid variables.$notification-error; } &.warning { - border-top: 12px solid #ffeb3b; + border-top: 12px solid colors.$orange200; } } .re-wrapper.thereAreIssues .re-open-view.re-issues { top: -1px; - border-top: 12px solid colors.$grey3; + border-top: 12px solid colors.$grey150; } section { @@ -308,12 +309,12 @@ section { .errorTaggingArea { .highlight { - background-color: #7eb30c; + background-color: colors.$green700; } } .errorTaggingArea::selection { - background-color: #ffeb3b; + background-color: colors.$orange200; } .translation-issues-button { @@ -331,7 +332,7 @@ section { gap: 6px; align-self: stretch; cursor: pointer; - border-radius: 8px; + border-radius: variables.$border-radius-default; width: 18px; height: 18px; margin-left: 8px; @@ -354,7 +355,7 @@ section { } .revise-button-2 { - background: colors.$approved2Green; + background: colors.$purple500; } } @@ -363,7 +364,7 @@ section { } .editing-highlight { - background-color: colors.$grey5 !important; + background-color: colors.$grey50 !important; } .editing-backward-container { @@ -384,8 +385,8 @@ section { //Download Button .downloadtr-button.approved-2ndpass { - background: colors.$approved2Green; - color: #fff !important; + background: colors.$purple500; + color: colors.$white !important; } .severities-dropdown-trigger { diff --git a/public/css/sass/components/SegmentsContainer.scss b/public/css/sass/components/SegmentsContainer.scss index 2e56987d49..63284373ff 100644 --- a/public/css/sass/components/SegmentsContainer.scss +++ b/public/css/sass/components/SegmentsContainer.scss @@ -1,4 +1,5 @@ -@use "../commons/colors"; +@use '../commons/colors'; +@use '../commons/variables'; .virtual-list { width: 100%; height: 100%; @@ -11,7 +12,7 @@ height: auto; section.editor { - border: 1px solid colors.$grey2; + border: 1px solid colors.$grey300; } } @@ -24,13 +25,13 @@ .row-border-radius-top { section { - border-top-left-radius: 8px; - border-top-right-radius: 8px; - border-top-color: colors.$grey2 !important; + border-top-left-radius: variables.$border-radius-default; + border-top-right-radius: variables.$border-radius-default; + border-top-color: colors.$grey300 !important; .body { - border-top-left-radius: 8px; - border-top-right-radius: 8px; + border-top-left-radius: variables.$border-radius-default; + border-top-right-radius: variables.$border-radius-default; overflow: hidden; } } @@ -42,27 +43,27 @@ .row-border-radius-bottom { section { - border-bottom-left-radius: 8px; - border-bottom-right-radius: 8px; + border-bottom-left-radius: variables.$border-radius-default; + border-bottom-right-radius: variables.$border-radius-default; &.editor { .footer { .tab { - border-bottom-left-radius: 8px; - border-bottom-right-radius: 8px; + border-bottom-left-radius: variables.$border-radius-default; + border-bottom-right-radius: variables.$border-radius-default; } } } } section.opened { - margin-bottom: 8px; + margin-bottom: variables.$border-radius-default; } section:not(.editor) { .body { - border-bottom-left-radius: 8px; - border-bottom-right-radius: 8px; + border-bottom-left-radius: variables.$border-radius-default; + border-bottom-right-radius: variables.$border-radius-default; overflow: hidden; } } @@ -75,5 +76,5 @@ > :not(:first-child) > div > :first-child:not(.editor) { - border-top-color: colors.$grey3; + border-top-color: colors.$grey150; } diff --git a/public/css/sass/components/UploadFile.scss b/public/css/sass/components/UploadFile.scss index 8c09c93aae..c5b5cb697d 100644 --- a/public/css/sass/components/UploadFile.scss +++ b/public/css/sass/components/UploadFile.scss @@ -1,6 +1,6 @@ @use '../commons/colors'; -.upload-files-container { - border: 1px dashed #ccc; +.upload-files-container, .upload-box-not-logged, .upload-waiting-logged { + border: 1px dashed colors.$grey200; min-height: 200px; border-radius: 4px; padding: 24px; @@ -16,7 +16,7 @@ align-items: flex-start; } &.isDragging { - background-color: colors.$grey7; + background-color: colors.$grey400; } .upload-files-start { display: flex; @@ -32,7 +32,7 @@ } span { font-size: 24px; - color: colors.$grey1 + color: colors.$grey500 } } .upload-files-list { @@ -44,7 +44,7 @@ grid-template-columns: 2fr 1fr 24px; align-items: center; padding: 8px; - border-bottom: 1px dashed #ccc; + border-bottom: 1px dashed colors.$grey200; &.zip-folder { padding-left: 40px; } @@ -57,21 +57,14 @@ font-size: 16px; max-width: 80%; } - .file-icon { - height: 30px; - min-width: 30px; - display: block; - background-size: 25px !important; - margin-bottom: 4px; - } .file-item-error { - color: colors.$redDefault; + color: colors.$red500; } .file-item-warning { - color: colors.$orangeDefault; + color: colors.$orange200; } .file-item-success { - color: colors.$greenDefault; + color: colors.$green500; } .file-item-info { display:flex; @@ -83,10 +76,10 @@ } .importing-progress { .progress { - background-color: colors.$approvedGreen; + background-color: colors.$green800; } .progress-wrapper { - background-color: rgba(colors.$approvedGreen, 0.24); + background-color: rgba(colors.$green800, 0.24); } } } diff --git a/public/css/sass/components/UserProjectDropdown.scss b/public/css/sass/components/UserProjectDropdown.scss index 85dc7df5ea..8284322347 100644 --- a/public/css/sass/components/UserProjectDropdown.scss +++ b/public/css/sass/components/UserProjectDropdown.scss @@ -1,102 +1,106 @@ @use '../commons/colors'; -.user-project-dropdown-container { +.user-project-dropdown-trigger { position: relative; + padding: 10px 10px 10px 1px !important; + transition-property: + color, background-color, box-shadow, opacity, padding !important; + background-color: colors.$grey100 !important; + border: 1px solid colors.$grey200 !important; + + &:disabled { + color: colors.$grey400 !important; + } - .dropdown { - position: absolute; - visibility: hidden; - z-index: 1; - background-color: white; - margin-top: 5px; - padding: 5px; - min-width: 250px; - right: 0; - max-height: 450px; - overflow: auto; - opacity: 0; - transition: opacity 0.2s linear; - box-shadow: 0px 2px 3px 0px rgba(34, 36, 38, 0.15); - - &.open { - visibility: visible; - opacity: 1; + &.not-assignee { + box-shadow: unset !important; + background-color: transparent !important; + border: 1px solid colors.$grey400; + + &:hover { + border-color: colors.$blue500; + color: colors.$blue500 !important; } - ul { - padding: 0; - margin: 0; - list-style: none; + > span { display: flex; - flex-direction: column; - - > li { - display: flex; - align-items: center; - gap: 5px; - cursor: pointer; - padding: 10px; - - &:hover { - background-color: colors.$grey9; - } - - &.active { - background-color: colors.$darkBlueHover; - color: colors.$white; - } - } + align-items: center; + gap: 10px; + padding: 0 10px; } } - .trigger-button { - position: relative; - padding: 10px 10px 10px 1px !important; - transition: padding 0.2s ease-out; + &:hover:not(:disabled):not(.not-assignee) { + padding-right: 32px !important; - &.not-assignee { - box-shadow: unset !important; - background-color: transparent !important; - border: 1px solid colors.$grey7; + .button-remove-assignee { + opacity: 1; + } + } +} - &:hover { - border-color: colors.$translatedBlue; - color: colors.$translatedBlue !important; - } +.button-remove-assignee { + position: absolute; + right: 3px; + display: flex; + width: 24px; + height: 24px; + justify-content: center; + align-items: center; + background-color: rgba(colors.$grey400, 0.5); + border-radius: 50%; + color: colors.$white; + transition: opacity 0.2s ease-in-out; + opacity: 0; + + &:hover { + background-color: rgba(colors.$grey400, 0.7); + } +} - > span { - display: flex; - align-items: center; - gap: 10px; - padding: 0 10px; - } - } +.user-project-dropdown-content { + background-color: white; + padding: 5px; + min-width: 250px; + max-height: 450px; + overflow: auto; + box-shadow: 0px 2px 3px 0px rgba(34, 36, 38, 0.15); + + ul { + padding: 0; + margin: 0; + list-style: none; + display: flex; + flex-direction: column; - &:disabled { - box-shadow: unset !important; - border: 1px solid colors.$grey8; - //color: $grey6 !important; - } + > li { + display: flex; + align-items: center; + gap: 5px; + cursor: pointer; + padding: 10px; - &:hover:not(:disabled):not(.not-assignee) { - padding-right: 32px !important; + &:hover { + background-color: colors.$grey75; + } - .button-remove-assignee { - visibility: visible; + &.active { + background-color: colors.$blue950; + color: colors.$white; } } } .add-new-member { - border-bottom: 1px solid colors.$grey8; + border-bottom: 1px solid colors.$grey200; margin-bottom: 10px; text-transform: uppercase; - color: colors.$translatedBlue; + color: colors.$blue500; font-weight: bold; justify-content: space-between; > svg { - border: 1px solid colors.$translatedBlue; + border: 1px solid colors.$blue500; border-radius: 50%; } } @@ -120,24 +124,6 @@ .no-results { text-align: center; - color: #9e9e9e; - } - - .button-remove-assignee { - visibility: hidden; - position: absolute; - right: 3px; - display: flex; - width: 24px; - height: 24px; - justify-content: center; - align-items: center; - background-color: rgba(colors.$grey7, 0.5); - border-radius: 50%; - color: colors.$white; - - &:hover { - background-color: rgba(colors.$grey7, 0.7); - } + color: colors.$grey400; } } diff --git a/public/css/sass/components/bulk-approve-bar/bulk_approve_bar.scss b/public/css/sass/components/bulk-approve-bar/bulk_approve_bar.scss index 696c174343..39534786d6 100644 --- a/public/css/sass/components/bulk-approve-bar/bulk_approve_bar.scss +++ b/public/css/sass/components/bulk-approve-bar/bulk_approve_bar.scss @@ -2,7 +2,7 @@ .bulk-approve-bar { position: relative; z-index: 2; - background: #edf4fd; + background: colors.$blue50; padding: 8px 10px; box-shadow: 0 0 4px rgba(0, 0, 0, 0.43); float: left; @@ -55,19 +55,19 @@ vertical-align: bottom; margin-right: 0; &:hover { - box-shadow: 0 0 0 #e0e0e0, 0 0 2px rgba(0, 0, 0, 0.12), + box-shadow: 0 0 0 colors.$grey200, 0 0 2px rgba(0, 0, 0, 0.12), 0 2px 4px rgba(0, 0, 0, 0.24) !important; } &.translated-all-bulked { - border: 1px solid colors.$translatedBlue; - color: colors.$translatedBlue; + border: 1px solid colors.$blue500; + color: colors.$blue500; } &.approved-all-bulked { - border: 1px solid colors.$approvedGreen; - color: colors.$approvedGreen; + border: 1px solid colors.$green800; + color: colors.$green800; &.approved-2nd-pass { - border: 1px solid colors.$approved2Green; - color: colors.$approved2Green; + border: 1px solid colors.$purple500; + color: colors.$purple500; } } i { diff --git a/public/css/sass/components/common/Accordion.scss b/public/css/sass/components/common/Accordion.scss index d5f176feec..4ae849928b 100644 --- a/public/css/sass/components/common/Accordion.scss +++ b/public/css/sass/components/common/Accordion.scss @@ -1,4 +1,5 @@ @use '../../commons/colors'; +@use '../../commons/variables'; .accordion-component { overflow: hidden; @@ -10,12 +11,13 @@ align-items: center; padding: 14px 24px; font: 12px; - background-color: colors.$grey3; - border-radius: 8px; + background-color: colors.$grey150; + border-radius: variables.$border-radius-default; cursor: pointer; &.accordion-expanded { - border-radius: 8px 8px 0 0; + border-radius: variables.$border-radius-default + variables.$border-radius-default 0 0; } > svg { @@ -36,6 +38,7 @@ transition-timing-function: 'ease-in-out'; transform-origin: top center; padding: 0 24px; - border-radius: 0 0 8px 8px; - background-color: colors.$grey4; + border-radius: 0 0 variables.$border-radius-default + variables.$border-radius-default; + background-color: colors.$grey100; } diff --git a/public/css/sass/components/common/Badge.scss b/public/css/sass/components/common/Badge.scss index b4a2d3e906..50809bf67b 100644 --- a/public/css/sass/components/common/Badge.scss +++ b/public/css/sass/components/common/Badge.scss @@ -13,7 +13,8 @@ white-space: nowrap; overflow: hidden; text-overflow: ellipsis; - + line-height: 24px; + justify-content: center; > svg { flex-shrink: 0; } @@ -22,8 +23,9 @@ // Type and Mode modifiers .badge-black { &.badge-default { - background-color: rgba(colors.$black, 0.5); - color: colors.$white; + border: solid 1px colors.$grey400; + background-color: rgba(colors.$grey400, 0.3); + color: colors.$black; } &.badge-full { @@ -38,90 +40,144 @@ .badge-primary { &.badge-default { - border: solid 1px colors.$translatedBlueTransparent; - background-color: rgba(colors.$translatedBlueTransparent, 0.24); - color: colors.$translatedBlue; + border: solid 1px colors.$blue200; + background-color: rgba(colors.$blue200, 0.24); + color: colors.$blue500; } &.badge-full { - background-color: rgba(colors.$translatedBlue, 0.72); + background-color: rgba(colors.$blue500, 0.72); color: colors.$white; } &.badge-outline { - border: solid 1px colors.$translatedBlue; - color: colors.$translatedBlue; + border: solid 1px colors.$blue500; + color: colors.$blue500; } } .badge-green { &.badge-default { - border: solid 1px colors.$approvedGreenTransparent; - background-color: rgba(colors.$approvedGreenTransparent, 0.24); - color: colors.$greenDefaultHover; + border: solid 1px colors.$green200; + background-color: rgba(colors.$green200, 0.24); + color: colors.$green700; } &.badge-full { - background-color: rgba(colors.$approvedGreen, 0.72); + background-color: rgba(colors.$green800, 0.72); color: colors.$white; } &.badge-outline { - border: solid 1px colors.$approvedGreen; - color: colors.$greenDefaultHover; + border: solid 1px colors.$green800; + color: colors.$green700; } } .badge-yellow { &.badge-default { - border: solid 1px colors.$orangeDefaultTransparent; - background-color: rgba(colors.$orangeDefaultTransparent, 0.24); - color: colors.$orangeDefaultHover; + border: solid 1px colors.$orange100; + background-color: rgba(colors.$orange100, 0.15); + color: colors.$orange400; } &.badge-full { - background-color: rgba(colors.$orangeDefault, 0.72); + background-color: rgba(colors.$orange200, 0.72); color: colors.$white; } &.badge-outline { - border: solid 1px colors.$orangeDefault; - color: colors.$orangeDefaultHover; + border: solid 1px colors.$orange200; + color: colors.$orange400; } } .badge-blue { &.badge-default { - border: solid 1px colors.$linkBlue; - background-color: rgba(colors.$linkBlue, 0.24); - color: colors.$linkBlue; + border: solid 1px colors.$blue700; + background-color: rgba(colors.$blue700, 0.15); + color: colors.$blue700; } &.badge-full { - background-color: rgba(colors.$linkBlue, 0.72); + background-color: rgba(colors.$blue700, 0.72); color: colors.$white; } &.badge-outline { - border: solid 1px colors.$linkBlue; - color: colors.$linkBlue; + border: solid 1px colors.$blue700; + color: colors.$blue700; } } .badge-red { &.badge-default { - border: solid 1px colors.$redDefault; - background-color: rgba(colors.$redDefault, 0.24); - color: colors.$redDefault; + border: solid 1px colors.$red500; + background-color: rgba(colors.$red500, 0.15); + color: colors.$red500; + } + + &.badge-full { + background-color: rgba(colors.$red500, 0.72); + color: colors.$white; + } + + &.badge-outline { + border: solid 1px colors.$red500; + color: colors.$red500; + } +} + +.badge-purple { + &.badge-default { + border: solid 1px colors.$purple500; + background-color: rgba(colors.$purple500, 0.15); + color: colors.$purple500; + } + + &.badge-full { + background-color: rgba(colors.$purple500, 0.72); + color: colors.$white; + } + + &.badge-outline { + border: solid 1px colors.$purple500; + color: colors.$purple500; + } +} + +.badge-orange { + &.badge-default { + border: solid 1px colors.$orange600; + background-color: rgba(colors.$orange600, 0.15); + color: colors.$orange600; + } + + &.badge-full { + background-color: rgba(colors.$orange600, 0.72); + color: colors.$white; + } + + &.badge-outline { + border: solid 1px colors.$orange600; + color: colors.$orange600; + } +} + +.badge-grey { + &.badge-default { + border: solid 1px colors.$grey500; + background-color: rgba(colors.$grey500, 0.15); + color: colors.$grey500; } &.badge-full { - background-color: rgba(colors.$redDefault, 0.72); + background-color: rgba(colors.$grey500, 0.72); color: colors.$white; } &.badge-outline { - border: solid 1px colors.$redDefault; - color: colors.$redDefault; + border: solid 1px colors.$grey500; + color: colors.$grey500; } } diff --git a/public/css/sass/components/common/Button.scss b/public/css/sass/components/common/Button.scss index 431fdb6e71..2ea2133c00 100644 --- a/public/css/sass/components/common/Button.scss +++ b/public/css/sass/components/common/Button.scss @@ -1,21 +1,23 @@ @use '../../commons/colors'; +@use '../../commons/variables'; button.button-component-container, a.button-component-container { + position: relative; appearance: none; + box-sizing: border-box; display: inline-flex; align-items: center; justify-content: center; - gap: 8px; + gap: 6px; border: none; background-color: transparent; text-decoration: none; white-space: nowrap; cursor: pointer; - display: flex; - border-radius: 4px; + border-radius: variables.$border-radius-default; width: auto; - font-weight: 500; + font-weight: 700; transition-property: color, background-color, box-shadow, opacity; transition-duration: 0.3s; transition-timing-function: cubic-bezier(0.77, 0, 0.175, 1); @@ -77,6 +79,31 @@ a.button-component-container { } } } + &.outlineBg { + box-shadow: inset 0 0 0 1px var(--btnBorderColor); + background-color: var(--btnBgColorOutline); + color: var(--btnTextColor); + + &:not(:disabled):global(.button--active) { + box-shadow: inset 0 0 0 1px var(--btnBorderColorActive); + background-color: var(--btnBgColorOutline); + } + + &:not(:disabled):hover { + box-shadow: inset 0 0 0 1px var(--btnBorderColorHover); + background-color: var(--btnBgColorSemitransAlt); + color: var(--btnTextColor); + } + + &:disabled { + box-shadow: inset 0 0 0 1px var(--btnBorderColorDisabled); + color: var(--btnAltTextColorDisabled); + background-color: var(--btnBgColorSemitransAlt); + svg { + color: var(--btnTextColorDisabled); + } + } + } &.ghost { color: var(--btnAltTextColor); @@ -100,7 +127,7 @@ a.button-component-container { color: var(--btnAltTextColor); &:not(:disabled):global(.button--active) { - color: colors.$grey8; + color: colors.$grey200; } &:not(:disabled):hover, @@ -115,35 +142,44 @@ a.button-component-container { // Size modifiers &.small { - height: 28px; - padding: 0 10px; - font-size: 12px; - font-weight: 500; + height: 32px; + padding: 6px 12px; + gap: 6px; + font: variables.$font-style-small; + font-weight: 700; } &.standard { height: 40px; - padding: 0 16px; - line-height: 40px; - font-size: 14px; - font-weight: bold; + padding: 10px 16px; + font: variables.$font-style-small; + gap: 6px; + font-weight: 700; } &.medium { - height: 40px; - padding: 0 16px; - line-height: 40px; - font-size: 16px; - font-weight: bold; + height: 48px; + padding: 12px 20px; + font: variables.$font-style-base; + gap: 8px; + font-weight: 700; } &.big { - height: 48px; - padding: 0 24px; - line-height: 48px; - font-size: 18px; - font-weight: bold; + height: 54px; + padding: 14px 28px; + gap: 10px; + font: variables.$font-style-big; + font-weight: 700; } - &.iconSmall { + &.iconXSmall { width: 24px; height: 24px; + padding: 4px; + line-height: 24px; + font-size: 12px; + } + &.iconSmall { + width: 32px; + height: 32px; + padding: 4px; line-height: 24px; font-size: 12px; } @@ -153,12 +189,18 @@ a.button-component-container { line-height: 40px; font-size: 14px; } - &.iconBig { + &.iconMedium { width: 48px; height: 48px; line-height: 48px; font-size: 16px; } + &.iconBig { + width: 56px; + height: 56px; + line-height: 56px; + font-size: 18px; + } &.fullWidth { width: 100%; } @@ -191,104 +233,161 @@ a.button-component-container { // Type modifiers .default { - --btnTextColor: #{colors.$grey6}; - --btnTextColorDisabled: #{colors.$grey8}; - --btnAltTextColor: #{colors.$grey6}; - --btnAltTextColorHover: #{colors.$grey}; - --btnAltTextColorDisabled: #{rgba(colors.$white, 0.12)}; + --btnTextColor: #{colors.$black}; + --btnTextColorDisabled: #{colors.$grey200}; + --btnAltTextColor: #{colors.$black}; + --btnAltTextColorHover: #{colors.$grey600}; + --btnAltTextColorDisabled: #{rgba(colors.$grey700, 0.12)}; - --btnBorderColor: #{colors.$grey8}; - --btnBorderColorHover: #{colors.$grey6}; - --btnBorderColorActive: #{colors.$grey6}; - --btnBorderColorDisabled: #{rgba(colors.$white, 0.12)}; + --btnBorderColor: #{colors.$grey200}; + --btnBorderColorHover: #{colors.$grey700}; + --btnBorderColorActive: #{colors.$grey700}; + --btnBorderColorDisabled: #{rgba(colors.$grey700, 0.12)}; + + --btnBgColor: #{colors.$white}; + --btnBgColorAlt: #{colors.$grey75}; + --btnBgColorSemitrans: #{rgba(colors.$white, 0.5)}; + --btnBgColorSemitransAlt: #{rgba(colors.$white, 0.5)}; + --btnBgColorOutline: #{rgba(colors.$white, 0.5)}; +} +.neutral { + --btnTextColor: #{colors.$black}; + --btnTextColorDisabled: #{colors.$grey200}; + --btnAltTextColor: #{colors.$black}; + --btnAltTextColorHover: #{colors.$grey600}; + --btnAltTextColorDisabled: #{rgba(colors.$grey700, 0.12)}; + + --btnBorderColor: #{colors.$grey200}; + --btnBorderColorHover: #{colors.$grey700}; + --btnBorderColorActive: #{colors.$grey700}; + --btnBorderColorDisabled: #{rgba(colors.$grey700, 0.12)}; --btnBgColor: #{colors.$white}; - --btnBgColorAlt: #{colors.$grey9}; + --btnBgColorAlt: #{colors.$grey75}; --btnBgColorSemitrans: #{rgba(colors.$white, 0.5)}; --btnBgColorSemitransAlt: #{rgba(colors.$white, 0.5)}; + --btnBgColorOutline: #{rgba(colors.$white, 0.5)}; } .primary { --btnTextColor: #{colors.$white}; --btnTextColorDisabled: #{colors.$white}; - --btnAltTextColor: #{colors.$translatedBlue}; - --btnAltTextColorHover: #{colors.$translatedBlueHover}; - --btnAltTextColorDisabled: #{rgba(colors.$translatedBlue, 0.24)}; - - --btnBorderColor: #{rgba(colors.$translatedBlue, 0.24)}; - --btnBorderColorHover: #{colors.$translatedBlueHover}; - --btnBorderColorActive: #{colors.$translatedBlue}; - --btnBorderColorDisabled: #{rgba(colors.$translatedBlue, 0.24)}; - - --btnBgColor: #{colors.$translatedBlue}; - --btnBgColorAlt: #{colors.$translatedBlueHover}; - --btnBgColorSemitrans: #{rgba(colors.$translatedBlue, 0.12)}; - --btnBgColorSemitransAlt: #{rgba(colors.$translatedBlue, 0.24)}; + --btnAltTextColor: #{colors.$blue500}; + --btnAltTextColorHover: #{colors.$blue600}; + --btnAltTextColorDisabled: #{rgba(colors.$blue500, 0.24)}; + + --btnBorderColor: #{rgba(colors.$blue500, 0.24)}; + --btnBorderColorHover: #{colors.$blue600}; + --btnBorderColorActive: #{colors.$blue500}; + --btnBorderColorDisabled: #{rgba(colors.$blue500, 0.24)}; + + --btnBgColor: #{colors.$blue500}; + --btnBgColorAlt: #{colors.$blue600}; + --btnBgColorSemitrans: #{rgba(colors.$blue500, 0.12)}; + --btnBgColorSemitransAlt: #{rgba(colors.$blue500, 0.24)}; + --btnBgColorOutline: #{rgba(colors.$blue500, 0.5)}; } .info { --btnTextColor: #{colors.$white}; --btnTextColorDisabled: #{colors.$white}; - --btnAltTextColor: #{colors.$linkBlue}; - --btnAltTextColorHover: #{colors.$linkBlueHover}; - --btnAltTextColorDisabled: #{rgba(colors.$linkBlue, 0.24)}; - - --btnBorderColor: #{rgba(colors.$linkBlue, 0.24)}; - --btnBorderColorHover: #{colors.$linkBlue}; - --btnBorderColorActive: #{colors.$linkBlue}; - --btnBorderColorDisabled: #{rgba(colors.$linkBlue, 0.24)}; - - --btnBgColor: #{colors.$linkBlue}; - --btnBgColorAlt: #{colors.$linkBlueHover}; - --btnBgColorSemitrans: #{rgba(colors.$linkBlue, 0.12)}; - --btnBgColorSemitransAlt: #{rgba(colors.$linkBlue, 0.24)}; + --btnAltTextColor: #{colors.$blue700}; + --btnAltTextColorHover: #{colors.$blue400}; + --btnAltTextColorDisabled: #{rgba(colors.$blue700, 0.24)}; + + --btnBorderColor: #{rgba(colors.$blue700, 0.24)}; + --btnBorderColorHover: #{colors.$blue700}; + --btnBorderColorActive: #{colors.$blue700}; + --btnBorderColorDisabled: #{rgba(colors.$blue700, 0.24)}; + + --btnBgColor: #{colors.$blue700}; + --btnBgColorAlt: #{colors.$blue400}; + --btnBgColorSemitrans: #{rgba(colors.$blue700, 0.12)}; + --btnBgColorSemitransAlt: #{rgba(colors.$blue700, 0.24)}; + --btnBgColorOutline: #{rgba(colors.$blue700, 0.5)}; } .success { --btnTextColor: #{colors.$white}; --btnTextColorDisabled: #{colors.$white}; - --btnAltTextColor: #{colors.$greenDefault}; - --btnAltTextColorHover: #{colors.$greenDefaultHover}; - --btnAltTextColorDisabled: #{rgba(colors.$greenDefault, 0.24)}; - - --btnBorderColor: #{rgba(colors.$greenDefault, 0.24)}; - --btnBorderColorHover: #{colors.$greenDefault}; - --btnBorderColorActive: #{colors.$greenDefault}; - --btnBorderColorDisabled: #{rgba(colors.$greenDefault, 0.24)}; - - --btnBgColor: #{colors.$greenDefault}; - --btnBgColorAlt: #{colors.$greenDefaultHover}; - --btnBgColorSemitrans: #{rgba(colors.$greenDefault, 0.12)}; - --btnBgColorSemitransAlt: #{rgba(colors.$greenDefault, 0.24)}; + --btnAltTextColor: #{colors.$green800}; + --btnAltTextColorHover: #{colors.$green600}; + --btnAltTextColorDisabled: #{rgba(colors.$green200, 0.24)}; + + --btnBorderColor: #{rgba(colors.$green800, 0.24)}; + --btnBorderColorHover: #{colors.$green800}; + --btnBorderColorActive: #{colors.$green800}; + --btnBorderColorDisabled: #{rgba(colors.$green800, 0.24)}; + + --btnBgColor: #{colors.$green800}; + --btnBgColorAlt: #{colors.$green600}; + --btnBgColorSemitrans: #{rgba(colors.$green800, 0.12)}; + --btnBgColorSemitransAlt: #{rgba(colors.$green800, 0.24)}; + --btnBgColorOutline: #{rgba(colors.$green800, 0.5)}; } .warning { --btnTextColor: #{colors.$white}; --btnTextColorDisabled: #{colors.$white}; - --btnAltTextColor: #{colors.$warning}; - --btnAltTextColorHover: #{colors.$warningHover}; - --btnAltTextColorDisabled: #{rgba(colors.$warning, 0.24)}; - - --btnBorderColor: #{rgba(colors.$warning, 0.24)}; - --btnBorderColorHover: #{colors.$warning}; - --btnBorderColorActive: #{colors.$warning}; - --btnBorderColorDisabled: #{rgba(colors.$warning, 0.24)}; - - --btnBgColor: #{colors.$warning}; - --btnBgColorAlt: #{colors.$warningHover}; - --btnBgColorSemitrans: #{rgba(colors.$warning, 0.12)}; - --btnBgColorSemitransAlt: #{rgba(colors.$warning, 0.24)}; + --btnAltTextColor: #{colors.$orange700}; + --btnAltTextColorHover: #{colors.$orange800}; + --btnAltTextColorDisabled: #{rgba(colors.$orange700, 0.24)}; + + --btnBorderColor: #{rgba(colors.$orange700, 0.24)}; + --btnBorderColorHover: #{colors.$orange700}; + --btnBorderColorActive: #{colors.$orange700}; + --btnBorderColorDisabled: #{rgba(colors.$orange700, 0.24)}; + + --btnBgColor: #{colors.$orange700}; + --btnBgColorAlt: #{colors.$orange800}; + --btnBgColorSemitrans: #{rgba(colors.$orange700, 0.12)}; + --btnBgColorSemitransAlt: #{rgba(colors.$orange700, 0.24)}; + --btnBgColorOutline: #{rgba(colors.$orange700, 0.5)}; } .critical { --btnTextColor: #{colors.$white}; --btnTextColorDisabled: #{colors.$white}; - --btnAltTextColor: #{colors.$redDefault}; - --btnAltTextColorHover: #{colors.$redDefaultHover}; - --btnAltTextColorDisabled: #{rgba(colors.$redDefault, 0.24)}; - - --btnBorderColor: #{rgba(colors.$redDefault, 0.24)}; - --btnBorderColorHover: #{colors.$redDefault}; - --btnBorderColorActive: #{colors.$redDefault}; - --btnBorderColorDisabled: #{rgba(colors.$redDefault, 0.24)}; - - --btnBgColor: #{colors.$redDefault}; - --btnBgColorAlt: #{colors.$redDefaultHover}; - --btnBgColorSemitrans: #{rgba(colors.$redDefault, 0.12)}; - --btnBgColorSemitransAlt: #{rgba(colors.$redDefault, 0.24)}; + --btnAltTextColor: #{colors.$red500}; + --btnAltTextColorHover: #{colors.$red600}; + --btnAltTextColorDisabled: #{rgba(colors.$red500, 0.24)}; + + --btnBorderColor: #{rgba(colors.$red500, 0.24)}; + --btnBorderColorHover: #{colors.$red500}; + --btnBorderColorActive: #{colors.$red500}; + --btnBorderColorDisabled: #{rgba(colors.$red500, 0.24)}; + + --btnBgColor: #{colors.$red500}; + --btnBgColorAlt: #{colors.$red600}; + --btnBgColorSemitrans: #{rgba(colors.$red500, 0.12)}; + --btnBgColorSemitransAlt: #{rgba(colors.$red500, 0.24)}; + --btnBgColorOutline: #{rgba(colors.$red500, 0.5)}; +} +.purple { + --btnTextColor: #{colors.$white}; + --btnTextColorDisabled: #{colors.$white}; + --btnAltTextColor: #{colors.$purple500}; + --btnAltTextColorHover: #{colors.$purple1000}; + --btnAltTextColorDisabled: #{rgba(colors.$purple500, 0.24)}; + + --btnBorderColor: #{rgba(colors.$purple500, 0.24)}; + --btnBorderColorHover: #{colors.$purple500}; + --btnBorderColorActive: #{colors.$purple500}; + --btnBorderColorDisabled: #{rgba(colors.$purple500, 0.24)}; + + --btnBgColor: #{colors.$purple500}; + --btnBgColorAlt: #{colors.$purple1000}; + --btnBgColorSemitrans: #{rgba(colors.$purple500, 0.12)}; + --btnBgColorSemitransAlt: #{rgba(colors.$purple500, 0.24)}; + --btnBgColorOutline: #{rgba(colors.$purple500, 0.5)}; +} + +.icon { + --btnAltTextColorDisabled: #{rgba(colors.$white, 0.12)}; + + --btnBorderColor: #{colors.$grey200}; + --btnBorderColorHover: #{colors.$grey700}; + --btnBorderColorActive: #{colors.$grey700}; + --btnBorderColorDisabled: #{rgba(colors.$white, 0.12)}; + + --btnBgColor: #{colors.$white}; + --btnBgColorAlt: #{colors.$grey75}; + --btnBgColorSemitrans: #{rgba(colors.$white, 0.5)}; + --btnBgColorSemitransAlt: #{rgba(colors.$white, 0.5)}; + --btnBgColorOutline: #{rgba(colors.$white, 0.5)}; } diff --git a/public/css/sass/components/common/Checkbox.scss b/public/css/sass/components/common/Checkbox.scss index 6d56c6bef2..46efdabdc7 100644 --- a/public/css/sass/components/common/Checkbox.scss +++ b/public/css/sass/components/common/Checkbox.scss @@ -30,24 +30,24 @@ position: relative; z-index: 1; flex-shrink: 0; - color: colors.$grey6; + color: colors.$grey700; } input[type='checkbox']:not(:disabled):checked, input[type='checkbox']:not(:disabled):indeterminate { & + svg { - color: colors.$translatedBlue; + color: colors.$blue500; } } input[type='checkbox']:disabled { & + svg { opacity: 0.4; - color: colors.$grey7; + color: colors.$grey400; } & ~ span { - color: colors.$grey7; + color: colors.$grey400; } } @@ -60,5 +60,5 @@ .errorMessage { margin-top: 8px; font-size: 12px; - color: colors.$redDefault; + color: colors.$red500; } diff --git a/public/css/sass/components/common/Dropdown.scss b/public/css/sass/components/common/Dropdown.scss index f577e3634c..75da9f6049 100644 --- a/public/css/sass/components/common/Dropdown.scss +++ b/public/css/sass/components/common/Dropdown.scss @@ -1,14 +1,15 @@ @use '../../commons/colors'; +@use '../../commons/variables'; // General dropdown .custom-dropdown { position: relative; margin-top: 0px; border-radius: 4px; - box-shadow: 0 0 16px rgba(colors.$grey6, 0.4); + box-shadow: 0 0 16px rgba(colors.$grey700, 0.4); width: 100%; height: auto; - background-color: colors.$grey5; + background-color: colors.$grey50; } /*.custom-dropdown::before { content: ''; @@ -23,7 +24,7 @@ .custom-dropdown::before { border-left: 8px solid transparent; border-right: 8px solid transparent; - border-bottom: 6px solid colors.$grey5; + border-bottom: 6px solid colors.$grey50; } .select__dropdown--setting-position { @@ -42,22 +43,24 @@ } .select__dropdown--is-reversed .custom-dropdown::before { margin-top: auto; - border-top: 6px solid colors.$grey5; + border-top: 6px solid colors.$grey50; border-bottom: none; } // Search bar .dropdown__search-bar { position: relative; - background-color: colors.$grey5; + background-color: colors.$grey50; box-shadow: none; padding: 0; + border-radius: variables.$border-radius-default; + input + svg { position: absolute; right: 12px; top: 50%; transform: translateY(-50%); - color: colors.$grey; + color: colors.$grey600; cursor: pointer; pointer-events: none; } @@ -68,7 +71,7 @@ .dropdown__search-bar input, .dropdown__search-bar input:hover, .dropdown__search-bar input:focus { - background-color: colors.$grey5; + background-color: colors.$grey50; border: none !important; box-shadow: none; } @@ -77,11 +80,11 @@ } .dropdown__search-bar-input::placeholder { - color: colors.$grey; + color: colors.$grey600; } .dropdown__search-bar-input--highlighted { - background-color: colors.$grey4 !important; + background-color: colors.$grey100 !important; } // Most popular options @@ -104,15 +107,23 @@ } .dropdown__most-popular::before { left: 0; - background-image: linear-gradient(to right, colors.$black, rgba(colors.$black, 0)); + background-image: linear-gradient( + to right, + colors.$black, + rgba(colors.$black, 0) + ); } .dropdown__most-popular::after { right: 0; - background-image: linear-gradient(to right, rgba(colors.$black, 0), colors.$black); + background-image: linear-gradient( + to right, + rgba(colors.$black, 0), + colors.$black + ); } .dropdown__most-popular-option { - color: colors.$translatedBlue; + color: colors.$blue500; cursor: pointer; &:hover, @@ -192,7 +203,7 @@ .code-badge { display: block; text-align: center; - background-color: colors.$grey7; + background-color: colors.$grey400; border-radius: 4px; padding: 2px 4px; color: colors.$white; @@ -200,20 +211,20 @@ white-space: nowrap; font-weight: normal !important; a { - color: colors.$white; + color: colors.$white; } } } .dropdown__option--is-highlighted-option, .dropdown__option:hover { - background-color: colors.$grey4; + background-color: colors.$grey100; } .dropdown__option--is-active-option, .dropdown__option.dropdown__option--is-active-option:hover { - color: colors.$grey6; - background-color: colors.$grey8; + color: colors.$grey700; + background-color: colors.$grey200; svg { opacity: 1; @@ -223,8 +234,8 @@ .dropdown__option--is-no-results-found, .dropdown__option.dropdown__option--is-no-results-found:hover { - color: colors.$grey2; - background-color: colors.$grey5; + color: colors.$grey300; + background-color: colors.$grey50; cursor: default; svg { @@ -312,7 +323,7 @@ align-items: center; height: 72px; padding: 0 40px; - box-shadow: inset 0 1px 0 0 colors.$grey6; + box-shadow: inset 0 1px 0 0 colors.$grey700; } .dropdown__footer-copy { diff --git a/public/css/sass/components/common/DropdownMenu.scss b/public/css/sass/components/common/DropdownMenu.scss index 8b69abc7f6..d1e96d04bc 100644 --- a/public/css/sass/components/common/DropdownMenu.scss +++ b/public/css/sass/components/common/DropdownMenu.scss @@ -9,7 +9,7 @@ max-height: var(--radix-dropdown-menu-content-available-height); overflow-y: auto; background-color: colors.$white; - color: colors.$grey6; + color: colors.$grey700; box-shadow: 0 0 12px rgba(0, 0, 0, 0.2); animation: 0.3s cubic-bezier(0.77, 0, 0.175, 1) forwards dropdownmenu-fadeIn; z-index: 7; @@ -36,7 +36,7 @@ .dropdownmenu-separator { margin: 2px 0; height: 1px; - background-color: colors.$grey8; + background-color: colors.$grey200; } .dropdownmenu-item { @@ -50,7 +50,7 @@ width: 100%; padding: 8px; white-space: nowrap; - color: colors.$grey6; + color: colors.$grey700; cursor: pointer; outline: none; @@ -59,23 +59,23 @@ padding-right: 40px; } &.critical:not([data-disabled]) { - color: colors.$redDefault; + color: colors.$red500; &:hover { - background-color: rgba(colors.$redDefaultHover, 0.24); - color: colors.$redDefault; + background-color: rgba(colors.$red600, 0.24); + color: colors.$red500; } } &:not([data-disabled]):hover, &[data-highlighted]:not([data-disabled]), &:not([data-disabled]).selected, &[data-state='checked']:not([data-disabled]) { - background-color: colors.$grey5 !important; - color: colors.$darkBlue !important; + background-color: colors.$grey50 !important; + color: colors.$blue900 !important; } &[data-disabled], &[data-disabled]:hover { - color: colors.$grey7; + color: colors.$grey400; cursor: not-allowed; opacity: 0.4; } @@ -84,7 +84,7 @@ &:not([data-disabled]):hover, &[data-highlighted]:not([data-disabled]), &[data-state='open'] { - background-color: rgba(colors.$grey7, 0.06); + background-color: rgba(colors.$grey400, 0.06); color: black; } } diff --git a/public/css/sass/components/common/EmailsBadge.scss b/public/css/sass/components/common/EmailsBadge.scss index e7636a8644..64af74ac1e 100644 --- a/public/css/sass/components/common/EmailsBadge.scss +++ b/public/css/sass/components/common/EmailsBadge.scss @@ -1,4 +1,5 @@ @use '../../commons/colors'; +@use '../../commons/variables'; .email-badge { display: flex; @@ -18,7 +19,7 @@ flex-wrap: wrap; align-items: flex-start; gap: 8px; - border-radius: 4px; + border-radius: variables.$border-radius-default; min-width: 0; width: 100%; min-height: 90px; @@ -27,7 +28,6 @@ outline: none; cursor: text; overflow-y: auto; - box-shadow: inset 0 1px 3px #ddd; border: 1px solid rgba(34, 36, 38, 0.15); background-color: white; } @@ -60,7 +60,7 @@ .email-badge-placeholder { position: absolute; inset: 12px; - color: colors.$grey7; + color: colors.$grey400; } .email-badge-item { @@ -69,7 +69,7 @@ } .email-badge-error { - color: colors.$redDefault; + color: colors.$red500; } .email-badge-tag { @@ -81,15 +81,15 @@ cursor: default; &.default { - background-color: colors.$grey7; + background-color: colors.$grey400; color: white; } &.selected { - background-color: colors.$translatedBlue; + background-color: colors.$blue500; color: colors.$white; } &.invalid { - background-color: colors.$redDefault; + background-color: colors.$red500; color: colors.$white; } } @@ -100,14 +100,14 @@ &:hover { background-color: transparent !important; - color: colors.$grey8 !important; + color: colors.$grey200 !important; } .selected & { - color: colors.$grey9 !important; + color: colors.$grey75 !important; &:hover { - color: colors.$grey8 !important; + color: colors.$grey200 !important; } } } diff --git a/public/css/sass/components/common/HomePageSection.scss b/public/css/sass/components/common/HomePageSection.scss index 8541f2adb2..e207e632c9 100644 --- a/public/css/sass/components/common/HomePageSection.scss +++ b/public/css/sass/components/common/HomePageSection.scss @@ -5,7 +5,7 @@ padding: 48px 0; display: flex; flex-direction: column; - background-color: colors.$darkBlue; + background-color: colors.$blue900; align-items: center; gap: 8px; h3 { @@ -27,12 +27,8 @@ } } } -.layout-container { - position: relative; +.layout__container { z-index: 2; - margin-left: auto; - margin-right: auto; - width: 100%; display: flex; flex-direction: column; h1 { @@ -59,7 +55,7 @@ margin-top: 0; font-size: 28px; line-height: 32px; - color: #333; + color: colors.$grey1300; } img { width: 64px; @@ -69,47 +65,42 @@ p { font-size: 18px; line-height: 24px; - color: colors.$grey6; + color: colors.$grey700; } } } } @media (max-width: 829px) { - .layout-container { - max-width: 382px; + .layout__container { .layout-grid { grid-template-columns: 1fr; } } } @media (min-width: 830px) { - .layout-container { - max-width: 766px; + .layout__container { .layout-grid { grid-template-columns: 1fr 1fr; } } } @media (min-width: 1024px) { - .layout-container { - max-width: 928px; + .layout__container { .layout-grid { grid-template-columns: 1fr 1fr; } } } @media (min-width: 1280px) { - .layout-container { - max-width: 1080px; + .layout__container { .layout-grid { grid-template-columns: 1fr 1fr; } } } @media (min-width: 1440px) { - .layout-container { - max-width: 1280px; + .layout__container { .layout-grid { grid-template-columns: 1fr 1fr 1fr; } diff --git a/public/css/sass/components/common/Input.scss b/public/css/sass/components/common/Input.scss index b079d98822..9c485950c4 100644 --- a/public/css/sass/components/common/Input.scss +++ b/public/css/sass/components/common/Input.scss @@ -24,8 +24,8 @@ input { width: 100%; height: 40px; - color: colors.$grey6; - border: 1px solid colors.$grey4; + color: colors.$grey700; + border: 1px solid colors.$grey100; padding: 12px; box-shadow: 2px 2px 4px 0px rgba(0, 0, 0, 0.0784313725) inset; font-size: 16px; @@ -40,7 +40,7 @@ border: none !important; } &::placeholder { - color: colors.$grey7; + color: colors.$grey400; opacity: 1; } &:hover { @@ -65,16 +65,16 @@ &.hasError, &.hasError:hover, &.hasError:focus { - box-shadow: inset 0 0 0 2px colors.$redDefault !important; + box-shadow: inset 0 0 0 2px colors.$red500 !important; } &:disabled { - background-color: colors.$grey9; + background-color: colors.$grey75; box-shadow: none; - color: colors.$grey8; + color: colors.$grey200; cursor: not-allowed; &::placeholder { - color: colors.$grey8; + color: colors.$grey200; } } } @@ -89,7 +89,7 @@ position: absolute; top: 12px; left: 12px; - color: colors.$grey8; + color: colors.$grey200; cursor: pointer; pointer-events: none; } @@ -98,7 +98,7 @@ left: 10px; } input:disabled + svg { - color: colors.$grey8 !important; + color: colors.$grey200 !important; } } @@ -120,7 +120,7 @@ .input-component-errorMessage { font-size: 12px; - color: colors.$redDefault; + color: colors.$red500; text-align: left; padding-left: 2px; } diff --git a/public/css/sass/components/common/LabelWithTooltip.scss b/public/css/sass/components/common/LabelWithTooltip.scss index 679398ee05..cb33848c49 100644 --- a/public/css/sass/components/common/LabelWithTooltip.scss +++ b/public/css/sass/components/common/LabelWithTooltip.scss @@ -39,7 +39,7 @@ padding: 4px 8px; background-color: colors.$white; box-shadow: 0 0 16px rgba(colors.$black, 0.25); - color: colors.$grey6; + color: colors.$grey700; white-space: normal; font-size: 14px; font-weight: normal; diff --git a/public/css/sass/components/common/MenuButton.scss b/public/css/sass/components/common/MenuButton.scss deleted file mode 100644 index 44f73d1ee0..0000000000 --- a/public/css/sass/components/common/MenuButton.scss +++ /dev/null @@ -1,110 +0,0 @@ -@use '../../commons/colors'; - -.menu-button { - display: flex; - justify-content: center; - font-size: 16px; -} - -.menu-button-wrapper { - display: flex; - cursor: pointer; - - button { - cursor: pointer; - } - - > button { - color: colors.$black; - background: colors.$grey4; - padding: 4px 8px; - text-align: center; - border: 1px solid colors.$grey7; - } - - .label { - border-radius: 2px 0 0 2px; - - &:hover { - background-color: colors.$grey5; - } - } - - .icon { - display: flex; - align-items: center; - border-radius: 0 2px 2px 0; - border-left: 0; - padding: 0 2px; - - &:hover { - color: colors.$grey7; - } - } -} - -.menu-button-items { - position: absolute; - z-index: 20; - display: flex; - flex-direction: column; - box-shadow: - 0 0 0 #e0e0e0, - 0 0 2px rgba(0, 0, 0, 0.12), - 0 2px 4px rgba(0, 0, 0, 0.24); - padding: 8px; - background-color: colors.$white; - margin-top: 10px; - - > :not(:last-child) { - border-bottom: solid 1px colors.$grey4; - } -} - -.menu-button-items-rect-arrow { - &::before { - content: ''; - border-left: 8px solid transparent; - border-right: 0px solid transparent; - border-bottom: 8px solid #ffffff; - bottom: 100%; - left: auto; - right: 0; - position: absolute; - } -} - -.menu-button-items-reversed { - transform: translateY(calc((100% + 4px) * -1)); - margin-top: 0px; - &::after { - content: ''; - border-left: 8px solid transparent; - border-right: 0px solid transparent; - border-top: 8px solid #ffffff; - top: 100%; - right: 0; - left: auto; - position: absolute; - } - &::before { - visibility: hidden; - } -} - -.menu-button-item { - display: flex; - align-items: center; - gap: 5px; - border: none; - padding: 8px; - text-align: left; - font-size: 16px; - background-color: unset; - cursor: pointer; - - &:not(:disabled):hover { - background-color: colors.$grey9; - color: colors.$translatedBlue; - } -} diff --git a/public/css/sass/components/common/NumericStepper.scss b/public/css/sass/components/common/NumericStepper.scss index 9e6e0b2f01..e951448095 100644 --- a/public/css/sass/components/common/NumericStepper.scss +++ b/public/css/sass/components/common/NumericStepper.scss @@ -1,15 +1,19 @@ @use '../../commons/colors'; +@use '../../commons/variables'; .numeric-stepper-component { display: flex; max-width: 70px; - height: 28px; + height: 32px; + border-radius: variables.$border-radius-default; input { width: 100%; height: 100%; outline: none; - border: 1px solid colors.$grey8; + border: 1px solid colors.$grey200; + border-radius: variables.$border-radius-default 0 0 + variables.$border-radius-default; text-align: center; } @@ -18,20 +22,21 @@ flex-direction: column; button { - height: 14px !important; + height: 16px !important; line-height: 1 !important; padding: 0 !important; - background: colors.$grey4 !important; - border: 1px solid colors.$grey7 !important; - border-radius: 0 !important; + background: colors.$grey100 !important; + border: 1px solid colors.$grey400 !important; + border-radius: 0 0 variables.$border-radius-default 0; &:hover { - background-color: colors.$grey5 !important; + background-color: colors.$grey50 !important; } } button:first-child { transform: rotate(180deg); + border-radius: 0 0 0 variables.$border-radius-default; } } } diff --git a/public/css/sass/components/common/Popover.scss b/public/css/sass/components/common/Popover.scss index 16dc255b0e..9af6e2e633 100644 --- a/public/css/sass/components/common/Popover.scss +++ b/public/css/sass/components/common/Popover.scss @@ -1,4 +1,5 @@ @use '../../commons/colors'; +@use '../../commons/variables'; .popover-component-container { position: relative; @@ -31,11 +32,11 @@ position: absolute; z-index: 4; - border-radius: 8px; + border-radius: variables.$border-radius-default; box-shadow: 0 0 24px rgba(colors.$black, 0.15); overflow: hidden; background-color: colors.$white; - border: 1px solid colors.$grey4; + border: 1px solid colors.$grey100; &.popover-component-left { left: 0; @@ -81,7 +82,7 @@ .popover-component-body { max-height: calc(100vh - 124px); padding: 0 16px; - color: colors.$grey6; + color: colors.$grey700; overflow-y: auto; } @@ -91,5 +92,5 @@ gap: 10px; padding: 10px; justify-content: flex-end; - // box-shadow: inset 0 1px 0 0 $grey8; + // box-shadow: inset 0 1px 0 0 $grey200; } diff --git a/public/css/sass/components/common/ProgressBar.scss b/public/css/sass/components/common/ProgressBar.scss index 9ec1092816..149cc054b3 100644 --- a/public/css/sass/components/common/ProgressBar.scss +++ b/public/css/sass/components/common/ProgressBar.scss @@ -48,7 +48,7 @@ align-items: center; gap: 8px; width: 100%; - color: colors.$grey6; + color: colors.$grey700; .labelProgress { width: auto; } @@ -57,22 +57,64 @@ // Type modifiers &.default { .progress-wrapper { - background-color: rgba(colors.$translatedBlue, 0.24); + background-color: rgba(colors.$blue500, 0.24); } .progress { - background-color: colors.$translatedBlue; + background-color: colors.$blue500; } .labelProgress span { - color: colors.$translatedBlue; + color: colors.$blue500; } &.complete { .progress { - background-color: colors.$approvedGreen; + background-color: colors.$green800; } .labelProgress span { - color: colors.$approvedGreen; + color: colors.$green800; } } } +} + +.job-progress-container { + display: flex; + gap: 12px; + align-items: center; +} + +.job-progress-bar { + position: relative; + display: flex; + min-width: 196px; + height: 8px; + border-radius: 10px; + background-color: colors.$black100; + overflow: hidden; + + .bar { + position: absolute; + height: 100%; + border-top-right-radius: 5px; + border-bottom-right-radius: 5px; + } + + .translated-bar { + z-index: 4; + background-color: colors.$blue500; + } + + .approved-bar { + z-index: 3; + background-color: colors.$green800; + } + + .approved-bar-2nd-pass { + z-index: 2; + background-color: colors.$purple500; + } + .warning-bar { + z-index: 1; + background-color: colors.$orange600; + } } \ No newline at end of file diff --git a/public/css/sass/components/common/SegmentedControl.scss b/public/css/sass/components/common/SegmentedControl.scss index a5a3984453..9ddc2a12c5 100644 --- a/public/css/sass/components/common/SegmentedControl.scss +++ b/public/css/sass/components/common/SegmentedControl.scss @@ -1,4 +1,5 @@ @use '../../commons/colors'; +@use '../../commons/variables'; .segmented-control__wrapper > label { display: block; @@ -10,8 +11,8 @@ position: relative; display: flex; user-select: none; - border-radius: 4px; - background-color: colors.$grey5; + border-radius: variables.$border-radius-default; + background-color: colors.$grey50; } .segmented-control__label { @@ -23,10 +24,10 @@ margin: 0; font-size: 16px; line-height: 48px; - color: colors.$grey1; + color: colors.$grey500; transition: color 0.3s cubic-bezier(0.77, 0, 0.175, 1); cursor: pointer; - + gap: 4px; .segmented-control--compact & { line-height: 40px; } @@ -36,7 +37,7 @@ } &:hover { - color: colors.$grey6; + color: colors.$grey700; } } @@ -60,6 +61,6 @@ content: ''; display: block; height: 100%; - border-radius: 4px; - background-color: colors.$translatedBlue; + border-radius: variables.$border-radius-default; + background-color: colors.$blue500; } diff --git a/public/css/sass/components/common/Select.scss b/public/css/sass/components/common/Select.scss index c649f363d6..e759efe4c3 100644 --- a/public/css/sass/components/common/Select.scss +++ b/public/css/sass/components/common/Select.scss @@ -1,4 +1,6 @@ @use '../../commons/colors'; +@use '../../commons/variables'; + //selects .select { user-select: none; @@ -48,8 +50,8 @@ .select { margin: 0; - border: 1px solid colors.$grey2; - border-radius: 2px; + border: 1px solid colors.$grey300; + border-radius: variables.$border-radius-default; padding: 4px 8px; outline: none; font-size: 14px; @@ -57,13 +59,11 @@ width: 100%; background-color: colors.$white; white-space: nowrap; - color: colors.$grey6; + color: colors.$grey700; transition: box-shadow 0.3s cubic-bezier(0.77, 0, 0.175, 1); - overflow: hidden; - text-overflow: ellipsis; display: block; &::placeholder { - color: colors.$grey1; + color: colors.$grey500; opacity: 1; } .icon-reset { @@ -71,6 +71,11 @@ align-items: center; height: 100%; } + > span { + overflow: hidden; + text-overflow: ellipsis; + display: block; + } } .select--is-focused { @@ -80,7 +85,7 @@ .select--is-invalid, .select--is-invalid:hover, .select--is-invalid:focus { - box-shadow: inset 0 0 0 2px colors.$redDefault !important; + box-shadow: inset 0 0 0 2px colors.$red500 !important; } .select-with-icon__wrapper { @@ -99,7 +104,7 @@ .select-with-icon__wrapper input + svg { right: 12px; - color: colors.$grey; + color: colors.$grey600; } .input--invisible, @@ -145,23 +150,23 @@ label inset: 0; z-index: 10; padding: 40px; - background-color: rgba(colors.$grey, 0.6); + background-color: rgba(colors.$grey600, 0.6); } // Disabled state .select--is-disabled { - //background-color: colors.$grey6; + //background-color: colors.$grey700; box-shadow: none; - color: colors.$grey7; + color: colors.$grey400; cursor: not-allowed; &::placeholder { - color: colors.$grey7; + color: colors.$grey400; opacity: 1; } & ~ svg { - color: colors.$grey7 !important; + color: colors.$grey400 !important; } } @@ -170,26 +175,27 @@ label z-index: 12; top: 0; } -.select, .select__dropdown-wrapper { - .new-color { - box-shadow: 0px 0px 0px 1px rgba(34, 36, 38, 0.25) inset; - background: #ffffff; - } - .draft-color { - background: colors.$grey1; - } - .translated-color, - .post-edited-color { - background: colors.$translatedBlue; - } - .approved-color { - background: colors.$approvedGreen; - } - .approved-2ndpass-color, .approved2-color { - background: colors.$approved2Green; - } - .rejected-color { - background: colors.$rebuttedRed; - } - +.select, +.select__dropdown-wrapper { + .new-color { + box-shadow: 0px 0px 0px 1px rgba(34, 36, 38, 0.25) inset; + background: colors.$white; + } + .draft-color { + background: colors.$grey500; + } + .translated-color, + .post-edited-color { + background: colors.$blue500; + } + .approved-color { + background: colors.$green800; + } + .approved-2ndpass-color, + .approved2-color { + background: colors.$purple500; + } + .rejected-color { + background: colors.$orange600; + } } diff --git a/public/css/sass/components/common/SpinnerLoader.scss b/public/css/sass/components/common/SpinnerLoader.scss new file mode 100644 index 0000000000..4f5a53ae4b --- /dev/null +++ b/public/css/sass/components/common/SpinnerLoader.scss @@ -0,0 +1,77 @@ +@use '../../commons/colors'; + +.spinner-loader { + position: fixed; + left: 50%; + top: 50%; + color: rgba(0, 0, 0, 0.87); + transform: translate(-50%, -50%); + + > span { + display: block; + } + + &::before { + position: absolute; + content: ''; + top: 0; + left: 50%; + border-radius: 50%; + border: 4px solid rgba(0, 0, 0, 0.1); + } + + &::after { + position: absolute; + content: ''; + top: 0; + left: 50%; + animation: loader 0.6s infinite linear; + border: 4px solid colors.$black; + border-radius: 50%; + box-shadow: 0 0 0 1px transparent; + + border-left-color: transparent; + border-right-color: transparent; + border-bottom-color: transparent; + } +} + +.spinner-loader-size-small { + > span { + margin-top: 25px; + font-size: 12px; + } + + &::before, + &::after { + width: 24px; + height: 24px; + margin: 0 0 0 -12px; + } +} +.spinner-loader-size-medium { + > span { + margin-top: 50px; + font-size: 16px; + } + + &::before, + &::after { + width: 42px; + height: 42px; + margin: 0 0 0 -21px; + } +} +.spinner-loader-size-large { + > span { + margin-top: 85px; + font-size: 24px; + } + + &::before, + &::after { + width: 74px; + height: 74px; + margin: 0 0 0 -37px; + } +} diff --git a/public/css/sass/components/common/Switch.scss b/public/css/sass/components/common/Switch.scss index 3a21089b09..3732e65f37 100644 --- a/public/css/sass/components/common/Switch.scss +++ b/public/css/sass/components/common/Switch.scss @@ -8,10 +8,10 @@ .switch-container-active, .switch-container-inactive { font-size: 14px; - color: colors.$grey6; + color: colors.$grey700; } .switch-container-active { - color: colors.$linkBlue; + color: colors.$blue700; } } .switch-container { @@ -35,7 +35,7 @@ right: 0; bottom: 0; border-radius: 12px; - background-color: colors.$grey7; + background-color: colors.$grey400; transition: background-color 0.2s ease-out; &::before { @@ -52,7 +52,7 @@ } input:checked + span { - background-color: colors.$linkBlue; + background-color: colors.$blue700; } input:checked + span::before { diff --git a/public/css/sass/components/common/TeamModal.scss b/public/css/sass/components/common/TeamModal.scss index cd4fe45a0c..9213c58de9 100644 --- a/public/css/sass/components/common/TeamModal.scss +++ b/public/css/sass/components/common/TeamModal.scss @@ -5,7 +5,7 @@ flex-direction: column; padding: 30px; gap: 30px; - height: 700px; + height: 685px; .team-name-container { align-items: center; @@ -39,7 +39,6 @@ } .button-invite { - display: flex; margin-left: auto; margin-top: 10px; } @@ -52,7 +51,7 @@ border-radius: 4px; padding: 6px; font-size: 15px; - color: #000; + color: colors.$black; transition: 0.6s; > input { @@ -72,7 +71,7 @@ margin-right: 2px; > svg { - color: colors.$grey6; + color: colors.$grey700; } } @@ -87,7 +86,7 @@ .no-result { font-size: 14px; - color: #666666; + color: colors.$grey700; padding: 7px; } @@ -106,10 +105,10 @@ } .removing-user-message { - color: colors.$grey1; + color: colors.$grey500; } - .button-remove { + .remove-user-button { margin-left: auto; } @@ -125,23 +124,6 @@ } } - .confirm-button { - height: 26px; - font-size: 14px !important; - min-width: unset; - gap: 5px !important; - border-radius: unset; - padding: 0 8px; - display: flex; - } - - .close-button { - width: 30px; - padding: 0 !important; - display: flex !important; - justify-content: center !important; - } - .pending-member-remove { display: flex; align-items: center; @@ -149,7 +131,7 @@ margin-left: auto; > span { - color: colors.$grey1; + color: colors.$grey500; font-size: 14px; } } @@ -169,7 +151,7 @@ width: 40px; max-width: 40px; height: 40px; - background-color: colors.$grey2; + background-color: colors.$grey300; border-radius: 50%; vertical-align: middle; text-align: center; @@ -187,13 +169,17 @@ > :not(:first-child) { font-size: 14px; - color: colors.$grey1; + color: colors.$grey500; } } - .button-close { - display: flex; + h5 { + margin-bottom: 10px; + } + + .submit-team-button { margin-left: auto; + width: 80px; } } @@ -202,18 +188,18 @@ height: 40px; padding: 0 10px; border-radius: 4px; - box-shadow: inset 0 1px 3px #ddd; + box-shadow: inset 0 1px 3px colors.$grey200; border: 1px solid rgba(34, 36, 38, 0.15); background-color: white; &:focus { outline: none; - border-color: colors.$linkBlueTransparent; + border-color: colors.$blue300; } } .team-modal-create { - height: 510px; + height: 485px; > p { margin: 0; diff --git a/public/css/sass/components/common/Tooltip.scss b/public/css/sass/components/common/Tooltip.scss index c9cd6df9c0..1e80f72b64 100644 --- a/public/css/sass/components/common/Tooltip.scss +++ b/public/css/sass/components/common/Tooltip.scss @@ -3,11 +3,11 @@ .tooltip-container { position: absolute; z-index: 12; - border-radius: 4px; + border-radius: 8px; padding: 5px 10px; background-color: colors.$white; box-shadow: 0 0 16px rgba(colors.$black, 0.25); - color: colors.$grey6; + color: colors.$grey700; pointer-events: none; white-space: normal; text-align: left; diff --git a/public/css/sass/components/common/UserDisconnectedBox.scss b/public/css/sass/components/common/UserDisconnectedBox.scss index d5a29e3de6..153555d20a 100644 --- a/public/css/sass/components/common/UserDisconnectedBox.scss +++ b/public/css/sass/components/common/UserDisconnectedBox.scss @@ -1,5 +1,6 @@ -@use "../../commons/colors"; -.user-disconnect-box{ +@use '../../commons/colors'; +@use '../../commons/variables'; +.user-disconnect-box { position: fixed; top: 0; right: 0; @@ -16,7 +17,7 @@ display: flex; flex-direction: column; margin: 0; - border-radius: 8px; + border-radius: variables.$border-radius-default; width: 100%; background-color: colors.$white; max-width: 500px; @@ -34,4 +35,4 @@ } } } -} \ No newline at end of file +} diff --git a/public/css/sass/components/common/UserMenu.scss b/public/css/sass/components/common/UserMenu.scss index 5fbc4885a2..939ad88621 100644 --- a/public/css/sass/components/common/UserMenu.scss +++ b/public/css/sass/components/common/UserMenu.scss @@ -10,13 +10,15 @@ color: colors.$white !important; } .header-button-signup { - color: colors.$darkBlue !important; + color: colors.$blue900 !important; } - +} +.user-menu-popover { + line-height: 0; } .user-menu-popover-avatar { - width: 35px; - height: 35px; + width: 40px; + height: 40px; border-radius: 20px; } @@ -26,12 +28,13 @@ padding: 20px 0; gap: 15px; min-width: 250px; + line-height: 1.2; > hr { margin: 0; border: none; height: 1px; - background-color: colors.$grey9; + background-color: colors.$grey75; } .user-info { @@ -84,10 +87,10 @@ width: 100%; display: block; text-decoration: none; - color: colors.$grey6; + color: colors.$grey700; &:hover { - background-color: colors.$grey5 !important; - color: colors.$darkBlue !important; + background-color: colors.$grey50 !important; + color: colors.$blue900 !important; } } } diff --git a/public/css/sass/components/header/FilesMenu.scss b/public/css/sass/components/header/FilesMenu.scss index ae8da1c5f0..d56ea9afe1 100644 --- a/public/css/sass/components/header/FilesMenu.scss +++ b/public/css/sass/components/header/FilesMenu.scss @@ -1,111 +1,44 @@ @use "../../commons/colors"; -.breadcrumbs { - display: grid; - grid-template-columns: 25px auto; - padding: 14px 0 4px 0; - position: relative; - .icon-container { - position: relative; - span#project-badge { - position: absolute; - left: -10px; - top: -8px; - font-family: Calibri, Arial, Helvetica, sans-serif !important; - color: #fff; - } - } - #pname-container { - margin: 0 10px 0 0; - overflow: hidden; - cursor: pointer; +.files-menu-button { + color: colors.$white !important; + text-decoration: underline !important; + &:hover { + text-decoration: none !important; } - .project-name { - color: #fff; - display: block; - text-decoration: underline; - &:hover { - text-decoration: none; - } + .filename-label .name { + max-width: 200px; } } - -.job-menu-files { - top: 50px; - display: block; - width: 315px; - background: colors.$grey3; - box-shadow: 0px 1px 12px #999; - z-index: 2; - padding: 0; - font-size: 14px; - position: absolute; - border: solid 1px #cdd4de; - .to-current { - background: #fff; - padding: 12px 16px; - cursor: pointer; - display: flex; - border-bottom: 1px solid colors.$grey2; - .icon-iconmoon:before { - color: #acb3bd; - font-size: 16px; - margin-right: 10px; - padding-right: 2px; - font-size: 16px; - content: '\f112'; - transform: rotate(180deg); - display: inline-block; - } - - .current-shortcut { - visibility: hidden; - padding-left: 8px; - } +.files-menu-header { + max-height: 340px; + .current-shortcut { + visibility: hidden; &:hover { - .current-shortcut { - visibility: visible; - } + visibility: visible; } } - .file-list-container { - overflow-y: auto; - max-height: 60vh; - .file-list-label { - padding: 6px 16px; - display: block; + .selected { + background: colors.$blue900; + color: colors.$white; + } + .dropdownmenu-item { + display: flex; + align-items: center; + justify-content: space-between; + &:first-child { + justify-content: flex-start; } - .file-list-item { - padding: 4px 6px; + > div { display: flex; align-items: center; - cursor: pointer; - .file-icon { - height: 33px; - padding: 5px; - margin: 0 8px 0 0; - width: 30px; - float: left; - background-size: 25px !important; - } - .file-name { - display: block; - max-width: 230px; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - } - span.current-icon { - margin-left: auto; - svg { - display: block; - margin-right: 8px; - } - } - &.current { - background: colors.$darkBlue; - color: #ffffff; - } + gap: 10px; + } + .file-name { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + max-width: 350px; } } } diff --git a/public/css/sass/components/header/TeamDropdown.scss b/public/css/sass/components/header/TeamDropdown.scss index c2b4701d53..edb4bd40fc 100644 --- a/public/css/sass/components/header/TeamDropdown.scss +++ b/public/css/sass/components/header/TeamDropdown.scss @@ -37,16 +37,16 @@ padding: 10px; &:hover { - background-color: colors.$grey9; + background-color: colors.$grey75; .container-icon-settings { visibility: visible; - color: colors.$translatedBlue; + color: colors.$blue500; } } &.active { - background-color: colors.$darkBlueHover; + background-color: colors.$blue950; color: colors.$white; .container-icon-settings { @@ -64,7 +64,6 @@ } .trigger-button { - height: 35px !important; border-radius: 20px; background-color: white !important; @@ -80,14 +79,14 @@ } .create-new-team { - border-bottom: 1px solid colors.$grey8; + border-bottom: 1px solid colors.$grey200; margin-bottom: 10px; text-transform: uppercase; - color: colors.$translatedBlue; + color: colors.$blue500; font-weight: bold; > svg { - border: 1px solid colors.$translatedBlue; + border: 1px solid colors.$blue500; border-radius: 50%; } } diff --git a/public/css/sass/components/header/header.scss b/public/css/sass/components/header/header.scss index 0b4cad827d..4445806972 100644 --- a/public/css/sass/components/header/header.scss +++ b/public/css/sass/components/header/header.scss @@ -1,4 +1,5 @@ -@use "../../commons/colors"; +@use '../../commons/colors'; +@use '../../commons/variables'; header { .revision-mark { /*float: left; @@ -13,19 +14,167 @@ header { line-height: 23px; color: white; text-align: center; - border-radius: 2px; - margin-top: 7px; - border: 1px solid #ffffff; + border-radius: 4px; + border: 1px solid colors.$white; &.revision-r1 { - background: colors.$approvedGreen; + background: colors.$green800; } &.revision-r2 { - background: colors.$approved2Green; + background: colors.$purple500; } } +} + +.markAsCompleteButton { + width: 40px !important; +} + +$icon-scale: 30px; + +/* Default */ + +header { + .wrapper { + grid-template-columns: + 208px minmax(0, 48px) minmax(120px, max-content) + auto max-content; /*208px minmax(0,48px) minmax(200px, max-content) auto 120px;*/ + align-items: center; + } + + .logo-menu { + display: grid; + align-items: center; + + .logo { + margin: 0; + background: url(/public/img/logo_matecat_big_white.svg) 0 0 no-repeat; + width: 190px; + height: 40px; + } + } + + .header-menu { + display: grid; + /*grid-template-columns: repeat(9, auto);*/ + grid-auto-flow: column; + align-items: center; + justify-content: right; + column-gap: 16px; + z-index: 4; + color: colors.$white; + margin-right: 16px; + button.qaButton, + .markAsCompleteButton, + > button { + color: colors.$white !important; + + &:disabled { + color: #{rgba(colors.$white, 0.5)} !important; + } + } - #files-instructions svg { - display: block; + .button-badge { + display: flex; + width: 16px; + height: 16px; + padding: 2px 6px; + justify-content: center; + align-items: center; + gap: 4px; + position: absolute; + right: -6px; + top: -4px; + background-color: white; + border-radius: 999px; + font-size: 12px; + line-height: 14px; + + &.button-badge-left { + right: unset; + left: -4px; + } + + &.button-badge-warning { + background-color: colors.$orange200; + color: colors.$white; + } + + &.button-badge-info { + background-color: colors.$blue500; + color: colors.$white; + } + + &.button-badge-error { + background-color: colors.$red500; + color: colors.$white; + } + + &.button-badge-success { + background-color: colors.$green800; + color: colors.$white; + } + } + + #action-filter { + &.active, + &.open { + opacity: 1; + + #filter { + fill: colors.$white; + } + } + } + + .comments-popover { + width: 300px; + max-height: 600px; + overflow: auto; + .popover-comments-container { + padding: 8px 0; + display: flex; + flex-direction: column; + gap: 4px; + + .popover-comments-item { + display: flex; + flex-direction: column; + gap: 8px; + padding: 8px; + border-radius: variables.$border-radius-default; + background-color: #{rgba(colors.$grey75, 0.5)}; + &.resolved { + background-color: #{rgba(colors.$green300, 0.15)}; + &:hover { + background-color: #{rgba(colors.$green300, 0.25)}; + } + } + &:hover { + background-color: colors.$grey75; + } + + .popover-comments-item-header { + display: flex; + flex-direction: column; + justify-content: flex-start; + align-items: flex-start; + gap: 4px; + font-size: 14px; + font-weight: 600; + margin-bottom: 4px; + color: colors.$grey1300; + + .popover-comments-item-name { + color: colors.$grey600; + } + } + + .popover-comments-item-text { + padding: 4px; + } + } + } + } } } diff --git a/public/css/sass/components/header/qaComponent.scss b/public/css/sass/components/header/qaComponent.scss index 251dcea454..e87b28a6de 100644 --- a/public/css/sass/components/header/qaComponent.scss +++ b/public/css/sass/components/header/qaComponent.scss @@ -8,166 +8,14 @@ } .qa-container { - background-color: #fff; + background-color: colors.$white; height: 50px; - box-shadow: 0 1px 3px #666; + box-shadow: 0 1px 3px colors.$grey700; border-radius: 0 0 2px 2px; display: block; - color: #4d4d4d; + color: colors.$grey700; } -.qa-issues-types { - display: flex; - flex-grow: 1; - flex-direction: row; - justify-content: flex-start; -} - -.qa-issues-container, -.qa-lexiqa-container { - width: 150px; - height: 50px; - align-items: center; - display: flex; - text-align: center; - justify-content: center; - font-size: 15px; - font-weight: normal; - position: relative; - cursor: pointer; - box-sizing: border-box; -} - -.qa-issues-container.segments-with-issues { - width: 190px; -} - -.qa-issues-container:hover, -.qa-lexiqa-container:hover { - background-color: #d0d0d0; -} - -.qa-issues-container.selected, -.qa-lexiqa-container.selected { - box-shadow: inset 0px -3px 0px #4d4d4d; -} - -.qa-counter { - width: 125px; - font-size: 16px; - color: #333; -} - -.icon-qa-issues, -.icon-qa-glossary, -.icon-conflicts, -.icon-qa-total-issues, -.icon-qa-lexiqa { - width: 30px; - height: 30px; - margin-right: 10px; - margin-top: 8px; -} - -.icon-conflicts { - margin-right: -2px; - margin-left: 15px; -} - -.icon-qa-total-issues:before { - content: '\e903'; - font-size: 25px; -} - -.icon-qa-glossary:before { - content: '\ea4f'; - font-size: 25px; -} - -.icon-conflicts:before { - content: '\f071'; - font-size: 25px; -} - -.icon-qa-issues:before { - content: '\ea7f'; - font-size: 25px; -} - -.icon-qa-lexiqa:before { - content: '\f044'; - font-size: 25px; - margin-top: 0px; - display: block; -} - -.qa-total-issues-counter { - top: 10px; - left: 10px; -} - -.qa-issues-counter { - top: 10px; - left: 25px; -} - -.qa-glossary-counter { - top: 10px; - left: 10px; -} - -.qa-conflicts-issues-counter { - top: 10px; - left: 15px; -} - -.qa-lexiqa-counter { - top: 10px; - left: 35px; -} - -.icon-qa-right-arrow:before { - content: '\ea3c'; - font-size: 18px; -} - -.icon-qa-left-arrow:before { - content: '\ea40'; - font-size: 18px; -} - -.qa-move-up, -.qa-move-down { - color: #797979; -} - -.qa-move-down { - margin-left: 15px; -} - -.qa-move-up:hover, -.qa-move-down:hover { - color: black; -} - -.qa-move-up:active, -.qa-move-down:active { - box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); - background-color: #eee; - background-image: -webkit-linear-gradient(top, #eee, #e0e0e0); -} - -.qa-arrows.qa-arrows-disabled .qa-move-up, -.qa-arrows.qa-arrows-disabled .qa-move-down, -.qa-arrows.qa-arrows-disabled .qa-move-up:hover, -.qa-arrows.qa-arrows-disabled .qa-move-down:hover { - cursor: default; - opacity: 0.5; - color: #797979; -} - -/************************************************/ - .qa-container { .qa-container-inside { height: 100%; @@ -179,6 +27,7 @@ .label-issues { font-weight: 700; margin-right: 5px; + &.labl { margin-left: 70px; } @@ -201,33 +50,35 @@ display: flex; flex-grow: 3; align-items: center; - .qa-issue { + > div { + display: flex; + gap: 8px; } .icon-cancel-circle { - color: #e1565a; + color: colors.$red400; } .icon-warning2 { - color: #ea862c; + color: colors.$orange600; } .ui.basic.buttons { button { font-size: 16px !important; padding: 10px; - color: #000000 !important; + color: colors.$black !important; font-family: calibri; display: flex; gap: 4px; &.error svg { - color: colors.$red800; + color: colors.$red400; } &.warning svg { - color: colors.$orangeDefault; + color: colors.$orange200; } &:hover { - background: #f2f4f7 !important; + background: colors.$grey50 !important; } &.mc-bg-gray { - background: #f2f4f7 !important; + background: colors.$grey50 !important; } } @@ -254,9 +105,17 @@ flex-direction: row; justify-content: flex-end; align-items: center; + .qa-arrows { + display: flex; + justify-content: center; + gap: 10px; + } .info-navigation-issues { - display: inline-block; - margin: 0 15px 0 10px; + display: flex; + align-items: center; + b { + margin-right: 2px; + } } } } diff --git a/public/css/sass/components/header/search.scss b/public/css/sass/components/header/search.scss index 1f5a4b25b2..a7b281987d 100644 --- a/public/css/sass/components/header/search.scss +++ b/public/css/sass/components/header/search.scss @@ -4,7 +4,7 @@ float: left; width: 100%; font-size: 12px; - background: #ffffff; + background: colors.$white; box-shadow: 0 0 4px rgba(0, 0, 0, 0.45); .block.buttons { margin-top: -6px !important; @@ -24,17 +24,16 @@ margin: 4px 0px 3px 10px; padding: 2px 10px; height: 28px; - background: #eeeeef; + background: colors.$grey100; cursor: pointer; font-size: 14px; width: fit-content; text-transform: uppercase; &:disabled { cursor: not-allowed; - background: #ffffff; - color: #d0d0d0; - color: #d0d0d0; - border: 1px solid #d0d0d0; + background: colors.$white; + color: colors.$grey200; + border: 1px solid colors.$grey200; font-weight: 100; } } @@ -47,20 +46,20 @@ font-size: 12px !important; height: 23px; padding: 0 5px; - border: 1px solid #abadb3; + border: 1px solid colors.$grey400; -webkit-transition: all 100ms ease-in; -moz-transition: all 100ms ease-in; } .search-input:hover { - -moz-box-shadow: inset 0 1px 1px #e6e7e8; - -webkit-box-shadow: inset 0 1px 1px #e6e7e8; + -moz-box-shadow: inset 0 1px 1px colors.$grey100; + -webkit-box-shadow: inset 0 1px 1px colors.$grey100; } .search-input:focus { - -moz-box-shadow: inset 0 1px 2px #ccc; - -webkit-box-shadow: inset 0 1px 2px #ccc; - color: #000; + -moz-box-shadow: inset 0 1px 2px colors.$grey200; + -webkit-box-shadow: inset 0 1px 2px colors.$grey200; + color: colors.$black; } @media only screen and (max-width: 1200px) { @@ -140,12 +139,12 @@ button#exec-replace { input:not(.input--invisible), { border-radius: 2px !important; border: 1px solid rgba(34, 36, 38, 0.15) !important; - box-shadow: inset 0 1px 3px #ddd !important; + box-shadow: inset 0 1px 3px colors.$grey200 !important; font-size: 1.2em !important; padding: 8px 16px 7px !important; &::-webkit-input-placeholder { - color: #929292; + color: colors.$grey400; } &:hover { @@ -153,21 +152,21 @@ button#exec-replace { } &:focus { - border-color: #85b7d9 !important; - background: #ffffff !important; + border-color: colors.$blue300 !important; + background: colors.$white !important; color: rgba(0, 0, 0, 0.8) !important; /*outline: none;*/ } } } .find-container { - background-color: #fff; + background-color: colors.$white; padding: 10px 0 0; margin-bottom: 0; - box-shadow: 0 1px 3px #666; + box-shadow: 0 1px 3px colors.$grey700; border-radius: 0 0 0 0; display: block; - color: #4d4d4d; + color: colors.$grey700; .find-container-inside { height: 100%; padding: 0 6.5% 0 5%; @@ -200,17 +199,17 @@ button#exec-replace { } .ui.cancel.label { padding: 4px; - background-color: #d6d6d6; + background-color: colors.$grey200; border-radius: 15px; top: 8px; line-height: 0px; right: 0px; &:hover { - background-color: #cccccc !important; + background-color: colors.$grey200 !important; } } .ui.input input { - box-shadow: inset 0 1px 3px #ddd; + box-shadow: inset 0 1px 3px colors.$grey200; } &.not-filtered { @@ -236,22 +235,22 @@ button#exec-replace { .circular.label { &.new-color { box-shadow: 0px 0px 0px 1px rgba(34, 36, 38, 0.25) inset; - background: #ffffff; + background: colors.$white; } &.draft-color { - background: #e8e8e8; + background: colors.$grey100; } &.translated-color { - background: colors.$translatedBlue; + background: colors.$blue500; } &.approved-color { - background: colors.$approvedGreen; + background: colors.$green800; } &.approved-2ndpass-color { - background: colors.$approved2Green; + background: colors.$purple500; } &.rejected-color { - background: #dc2e34; + background: colors.$red400; } } } @@ -296,7 +295,7 @@ button#exec-replace { .find-clear { margin-left: 13px; - border-left: 1px solid #d6d6d7; + border-left: 1px solid colors.$grey200; padding-left: 15px; position: relative; top: 9px; @@ -326,23 +325,7 @@ button#exec-replace { display: flex; justify-content: flex-end; align-items: flex-start; - margin-top: 4px; - button { - border-radius: 2px; - &:hover, - &.active { - box-shadow: 0 0 0 1px #0055b8 inset; - color: #0055b8 !important; - background: #fff !important; - } - - &:last-child { - width: max-content; - } - &.disabled { - box-shadow: 0px 0px 0px 1px rgba(34, 36, 38, 0.15) inset !important; - } - } + gap: 8px; } .find-option { display: flex; @@ -359,7 +342,7 @@ button#exec-replace { font-size: 1.2em; padding: 15px 6.5% 15px 5%; text-align: left; - background: #f2f4f7; + background: colors.$grey50; .found { margin: 0; margin-right: 20px; @@ -376,6 +359,9 @@ button#exec-replace { } .search-result-buttons { display: flex; + justify-content: center; + gap: 8px; + align-items: center; p { padding: 8px 5px; margin-bottom: 0; @@ -391,7 +377,7 @@ button#exec-replace { span { position: absolute; font-size: 12px; - color: #878788; + color: colors.$grey400; -webkit-transition: all 100ms ease-in; -moz-transition: all 100ms ease-in; visibility: hidden; @@ -426,7 +412,7 @@ button#exec-replace { } .custom-dropdown.select__dropdown { - background-color: #fff; + background-color: colors.$white; } ul.dropdown__list { diff --git a/public/css/sass/components/header/segmentsFilter.scss b/public/css/sass/components/header/segmentsFilter.scss index 9158ccb612..dd7450ccbd 100644 --- a/public/css/sass/components/header/segmentsFilter.scss +++ b/public/css/sass/components/header/segmentsFilter.scss @@ -1,6 +1,6 @@ @use "../../commons/colors"; body section.muted { - background: #f2f4f7; + background: colors.$grey50; cursor: not-allowed; .body { .text { @@ -29,11 +29,11 @@ body section.muted { } .search-settings-panel { - background: #efefef; + background: colors.$grey75; padding: 10px; position: absolute; width: 205px; - border: 1px solid #666; + border: 1px solid colors.$grey700; top: 48px; } @@ -46,7 +46,7 @@ header .filter:before { header .filter { display: block !important; text-decoration: none; - color: #eee; + color: colors.$grey75; box-shadow: none; border: 0; padding: 12px; @@ -91,7 +91,7 @@ body.cattool .filter:hover { cursor: pointer; } body.cattool .filter:hover { - color: #ccc; + color: colors.$grey200; } .cattool header .filter { @@ -110,7 +110,7 @@ body.cattool .filter:hover { .search-settings-info { float: left; margin-right: 10px; - color: #666; + color: colors.$grey700; } .filter-segments-count { @@ -142,17 +142,17 @@ section.muted .segment-side-buttons { float: left; margin-top: 1px; .filter-container { - background-color: #fff; + background-color: colors.$white; height: 50px; - box-shadow: 0 1px 3px #666; + box-shadow: 0 1px 3px colors.$grey700; border-radius: 0 0 2px 2px; display: block; - color: #4d4d4d; + color: colors.$grey700; //TODO: Transform in SCSS Component for all INPUT TYPES input:not(.input--invisible) { border-radius: 2px !important; border: 1px solid rgba(34, 36, 38, 0.15) !important; - box-shadow: inset 0 1px 3px #ddd !important; + box-shadow: inset 0 1px 3px colors.$grey200 !important; font-size: 1.2em !important; padding: 8px 16px 7px !important; &::-webkit-input-placeholder { @@ -162,8 +162,8 @@ section.muted .segment-side-buttons { border-color: rgba(34, 36, 38, 0.35) !important; } &:focus { - border-color: #85b7d9 !important; - background: #ffffff !important; + border-color: colors.$blue300 !important; + background: colors.$white !important; color: rgba(0, 0, 0, 0.8) !important; outline: none; } @@ -202,21 +202,21 @@ section.muted .segment-side-buttons { font-size: 16px; } .custom-dropdown.select__dropdown { - background-color: #fff; + background-color: colors.$white; min-width: 120px; } .filter-category .select__dropdown-wrapper { width: unset; } .select__dropdown { - background-color: #fff; + background-color: colors.$white; min-width: 120px; } .switch-container-outer { padding: 0 10px; } .switch-container input:checked + span { - background-color: colors.$grey7; + background-color: colors.$grey400; } &:nth-child(2) { margin-left: 15px; @@ -231,9 +231,9 @@ section.muted .segment-side-buttons { &:hover, &.active { - box-shadow: 0 0 0 1px #0055b8 inset; - color: #0055b8 !important; - background: #fff !important; + box-shadow: 0 0 0 1px colors.$blue400 inset; + color: colors.$blue400 !important; + background: colors.$white !important; } .text { @@ -244,14 +244,14 @@ section.muted .segment-side-buttons { .ui.cancel.label { position: absolute; padding: 4px; - background-color: #d6d6d6; + background-color: colors.$grey200; border-radius: 15px; top: 8px; line-height: 0px; right: 0px; visibility: hidden; &:hover { - background-color: #cccccc !important; + background-color: colors.$grey200 !important; } } } @@ -274,10 +274,10 @@ section.muted .segment-side-buttons { } &.filtered { .ui.basic.button { - background-color: #ffffff !important; - box-shadow: 0 0 0 #e0e0e0, 0 0 2px rgba(0, 0, 0, 0.12), + background-color: colors.$white !important; + box-shadow: 0 0 0 colors.$grey200, 0 0 2px rgba(0, 0, 0, 0.12), 0 2px 4px rgba(0, 0, 0, 0.24) !important; - color: #000000 !important; + color: colors.$black !important; padding: 9px 20px 9px 15px; &:hover { width: fit-content; @@ -303,23 +303,23 @@ section.muted .segment-side-buttons { .circular.label { &.new-color { box-shadow: 0px 0px 0px 1px rgba(34, 36, 38, 0.25) inset; - background: #ffffff; + background: colors.$white; } &.draft-color { - background: colors.$grey1; + background: colors.$grey500; } &.translated-color, &.post-edited-color { - background: colors.$translatedBlue; + background: colors.$blue500; } &.approved-color { - background: colors.$approvedGreen; + background: colors.$green800; } &.approved-2ndpass-color { - background: colors.$approved2Green; + background: colors.$purple500; } &.rejected-color { - background: colors.$rebuttedRed; + background: colors.$orange600; } } } @@ -333,11 +333,11 @@ section.muted .segment-side-buttons { float: none; label { &:before { - background: #dcdfe4 !important; + background: colors.$grey150 !important; } &:after { box-shadow: inset 0 0 0 1px rgba(34, 36, 38, 0.25); - background: #ffffff; + background: colors.$white; } } } @@ -366,7 +366,7 @@ section.muted .segment-side-buttons { } .clear-filter-element { margin-left: 13px; - border-left: 1px solid #d6d6d7; + border-left: 1px solid colors.$grey200; padding-left: 13px; color: black; display: flex; @@ -401,6 +401,12 @@ section.muted .segment-side-buttons { flex-direction: row; justify-content: flex-end; align-items: center; + .filter-arrows { + display: flex; + justify-content: center; + gap: 8px; + align-items: center; + } .info-navigation-filters { display: inline-block; margin: 0 15px 0 10px; @@ -479,10 +485,10 @@ section.muted .segment-side-buttons { padding: 10px; position: relative; &:hover { - background-color: colors.$grey4; + background-color: colors.$grey100; } &.active { - background-color: colors.$grey8; + background-color: colors.$grey200; } } } @@ -496,11 +502,11 @@ section.muted .segment-side-buttons { height: 38px !important; &:disabled { box-shadow: unset !important; - border: 1px solid colors.$grey8; - color: colors.$grey6 !important; + border: 1px solid colors.$grey200; + color: colors.$grey700 !important; opacity: 0.5; svg { - color: colors.$grey6 !important; + color: colors.$grey700 !important; opacity: 0.5; } } diff --git a/public/css/sass/components/pages/ActivityLogPage.scss b/public/css/sass/components/pages/ActivityLogPage.scss index ef6c33d122..7c7247aa73 100644 --- a/public/css/sass/components/pages/ActivityLogPage.scss +++ b/public/css/sass/components/pages/ActivityLogPage.scss @@ -18,7 +18,7 @@ .activity-log-table { height: 100%; overflow-y: auto; - border: 1px solid colors.$grey8; + border: 1px solid colors.$grey200; .activity-log-table-columns-name, .activity-log-table-columns-content { @@ -47,7 +47,7 @@ .activity-log-table-columns-content { > * { height: 40px; - border: 1px solid colors.$grey8; + border: 1px solid colors.$grey200; border-top: unset; padding: 10px; border-left: unset; @@ -58,13 +58,13 @@ } &:nth-child(odd) { - background-color: colors.$grey5; + background-color: colors.$grey50; } } .activity-table-column-order { - background-color: colors.$grey9; - border: 1px solid colors.$grey8; + background-color: colors.$grey75; + border: 1px solid colors.$grey200; padding: 5px; justify-content: space-between; cursor: pointer; @@ -97,7 +97,7 @@ width: 160px; label { - color: colors.$grey6; + color: colors.$grey700; } .select { @@ -105,7 +105,7 @@ padding: 5px; &:hover { - border-color: rgba(colors.$grey8, 0.8); + border-color: rgba(colors.$grey200, 0.8); box-shadow: none; } } @@ -115,7 +115,7 @@ width: 250px; font-size: 14px; border-radius: 2px; - border: 1px solid colors.$grey2; + border: 1px solid colors.$grey300; padding: 7px; } } diff --git a/public/css/sass/components/pages/ApiDocPage.scss b/public/css/sass/components/pages/ApiDocPage.scss index d0cf75abc3..45b55f27a7 100644 --- a/public/css/sass/components/pages/ApiDocPage.scss +++ b/public/css/sass/components/pages/ApiDocPage.scss @@ -1,3 +1,4 @@ +@use '../../commons/colors'; /*API DOC page*/ @@ -33,36 +34,36 @@ h3 { margin: 0px 0 0 0; padding: 0; font-size: 18px; - color: #999999 !important; + color: colors.$grey400 !important; font-weight: normal !important; } .tablestats { - border-right: 1px solid #ccc; + border-right: 1px solid colors.$grey200; } .tablestats th { - background-color: #efefef; + background-color: colors.$grey75; } .tablestats td, .tablestats th { - border-bottom: 1px solid #ccc; - border-left: 1px solid #ccc; + border-bottom: 1px solid colors.$grey200; + border-left: 1px solid colors.$grey200; padding: 6px 8px; margin: 1px 0; text-align: center; } .tablestats tr:hover { - background: #f7f8f9; + background: colors.$grey50; } .tablestats { - border-top: 1px solid #ccc; + border-top: 1px solid colors.$grey200; margin-bottom: 40px; - -moz-box-shadow: 0 1px 2px #ccc; - background: #fff; + -moz-box-shadow: 0 1px 2px colors.$grey200; + background: colors.$white; } .tablestats.continue { @@ -82,7 +83,7 @@ h3 { font-weight: bold !important; font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 18px; - color: #000 !important; + color: colors.$black !important; } .searchbox { @@ -95,7 +96,7 @@ h3 { .api .block-swagger { margin-top: -20px; - background: #fafafa; + background: colors.$grey50; } /* Bruteforce Override style.css and legacy.min.css */ @@ -114,7 +115,7 @@ section { /* Bruteforce Override style.css and legacy.min.css */ .api a { - color: #39699a; + color: colors.$blue400; } .api .menu { @@ -137,7 +138,7 @@ section { .api dt { float: left; text-align: left; - color: #666666; + color: colors.$grey700; width: 100px; padding-right: 20px; } @@ -170,12 +171,12 @@ section { .api h1, .api h2 { - color: #000 !important; + color: colors.$black !important; margin-top: 20px; } .api h3 { - color: #000 !important; + color: colors.$black !important; font-weight: bold !important; font-size: 22px !important; margin-bottom: 20px; @@ -187,7 +188,7 @@ section { margin: 10px 0; display: block; padding-bottom: 20px; - border-bottom: 1px dashed #ccc; + border-bottom: 1px dashed colors.$grey200; } .api .gototop.last { @@ -291,8 +292,8 @@ table { code { padding: 2px 4px; font-size: 90%; - color: #39699a; - background-color: #f4f4f4; + color: colors.$blue400; + background-color: colors.$grey75; white-space: nowrap; border-radius: 4px; } @@ -300,18 +301,18 @@ code { .req, .opt { font-family: inherit; - color: #c7254e; - background-color: #f9f2f4; + color: colors.$red400; + background-color: colors.$grey75; white-space: nowrap; padding: 2px 4px; - border-left: 2px solid #c7254e; + border-left: 2px solid colors.$red400; border-radius: 4px; } .opt { - background-color: #dff0d8; - border-left: 2px solid #3c763d; - color: #3c763d; + background-color: colors.$green50; + border-left: 2px solid colors.$green600; + color: colors.$green600; } .api p { @@ -326,54 +327,54 @@ code { } .outsource-btn { - border: 1px solid #666; + border: 1px solid colors.$grey700; border-radius: 4px; color: white; outline: 0; opacity: 0.9; padding: 0px !important; - border: 1px solid #ccc; + border: 1px solid colors.$grey200; cursor: pointer; } .outsource-btn:hover { - -moz-box-shadow: 0 0px 2px #666; - -webkit-box-shadow: 0 0px 2px #666; - box-shadow: 0 0px 2px #666; + -moz-box-shadow: 0 0px 2px colors.$grey700; + -webkit-box-shadow: 0 0px 2px colors.$grey700; + box-shadow: 0 0px 2px colors.$grey700; } .outsource-btn:active .outsource-price { - -moz-box-shadow: inset 0 0 5px 2px #888; - -webkit-box-shadow: inset 0 0 5px 2px #888; - box-shadow: inset 0 0 5px 2px #888; + -moz-box-shadow: inset 0 0 5px 2px colors.$grey400; + -webkit-box-shadow: inset 0 0 5px 2px colors.$grey400; + box-shadow: inset 0 0 5px 2px colors.$grey400; } .outsource-btn:active .outsource-delivery { - -moz-box-shadow: inset 0 -1px 2px 1px #888; - -webkit-box-shadow: inset 0 -1px 2px 1px #888; - box-shadow: inset 0 -1px 2px 1px #888; + -moz-box-shadow: inset 0 -1px 2px 1px colors.$grey400; + -webkit-box-shadow: inset 0 -1px 2px 1px colors.$grey400; + box-shadow: inset 0 -1px 2px 1px colors.$grey400; } .outsource-price { text-align: center; display: block; font-size: 18px; - background: #7eaf3e; + background: colors.$green300; font-weight: bold; padding: 10px; } .outsource-delivery { - background: #f4f4f4; + background: colors.$grey75; display: block; padding: 5px; margin-top: -5px; line-height: 18px; font-size: 12px; border-radius: 4px; - color: #333; + color: colors.$grey1300; - border-top: 1px solid #ccc; + border-top: 1px solid colors.$grey200; } .outsource-delivery strong { @@ -385,7 +386,7 @@ code { .lang-info { margin-top: 40px; margin-left: 10px; - color: #666; + color: colors.$grey700; font-size: 20px; } @@ -395,22 +396,22 @@ code { td[data-vote='Excellent'], td[data-vote='Verygood'], td[data-vote='Good'] { - background: #d8ead3; + background: colors.$green50; } .revision-info tr[data-vote='Poor'], td[data-vote='Poor'] { - background: #fdd7a4; + background: colors.$orange50; } .revision-info tr[data-vote='Acceptable'], td[data-vote='Acceptable'] { - background: #fff3cd; + background: colors.$orange50; } .revision-info tr[data-vote='Fail'], td[data-vote='Fail'] { - background: #f4cdcc; + background: colors.$red100; } .tablestats.revision { @@ -440,7 +441,7 @@ td[data-vote='Fail'] { #details-link { font-size: 16px; - color: #999; + color: colors.$grey400; text-shadow: none; margin-top: 15px; display: block; @@ -467,7 +468,7 @@ td[data-vote='Fail'] { #vote-box { width: 217px; - background: #f7f7f7; + background: colors.$grey50; height: 85px; position: absolute; right: 0px; @@ -479,8 +480,8 @@ td[data-vote='Fail'] { padding: 50px 5px 10px; z-index: 100000000; border-radius: 4px; - border: 1px solid #ececec; - box-shadow: 1px 1px 0px #e6e6e6; + border: 1px solid colors.$grey100; + box-shadow: 1px 1px 0px colors.$grey100; } .vote-area { @@ -497,27 +498,27 @@ td[data-vote='Fail'] { .blueline { width: 100%; height: 1px; - background: #09beec; + background: colors.$blue200; float: left; - box-shadow: 0px 1px 0px #ccc; + box-shadow: 0px 1px 0px colors.$grey200; } #vote-box[data-vote='Excellent'], #vote-box[data-vote='Verygood'], #vote-box[data-vote='Good'] { - color: #3c9423; + color: colors.$green700; } #vote-box[data-vote='Acceptable'] { - color: #eaba22; + color: colors.$orange400; } #vote-box[data-vote='Poor'] { - color: #ffa935; + color: colors.$orange600; } #vote-box[data-vote='Fail'] { - color: #e7504d; + color: colors.$red400; } table.tablestats.revision-info td, @@ -530,19 +531,19 @@ table.tablestats.revision-info th { .qa_eq_tr[data-vote='Excellent'] td, .qa_eq_tr[data-vote='Verygood'] td, .qa_eq_tr[data-vote='Good'] td { - border-color: #3c9423 !important; + border-color: colors.$green700 !important; } .qa_eq_tr[data-vote='Acceptable'] td { - border-color: #e5b007 !important; + border-color: colors.$orange400 !important; } .qa_eq_tr[data-vote='Poor'] td { - border-color: #ffa935 !important; + border-color: colors.$orange600 !important; } .qa_eq_tr[data-vote='Fail'] td { - border-color: #e7504d !important; + border-color: colors.$red400 !important; } .qa_eq_tr { @@ -570,7 +571,7 @@ table.tablestats.revision-info th { font-size: 22px; margin-bottom: 20px; font-weight: bold !important; - color: #333 !important; + color: colors.$grey1300 !important; } .vote-howto h2 { @@ -581,9 +582,9 @@ table.tablestats.revision-info th { blockquote { padding: 10px 20px; margin: 20px 30px 30px 30px; - background: #eee; + background: colors.$grey75; font-size: 16px; - border-left: 5px solid #aaa; + border-left: 5px solid colors.$grey400; width: 700px; } @@ -617,8 +618,8 @@ blockquote { overflow: scroll; } .pee-page header { - border-bottom: 1px solid #5c5c5c; - background-color: #4d4d4d; + border-bottom: 1px solid colors.$grey700; + background-color: colors.$grey700; padding: 0px 0 2px 0; margin-bottom: 20px; height: 45px; @@ -653,7 +654,7 @@ blockquote { position: relative; float: left; width: 4%; - text-shadow: 0px 0px 2px #fff; + text-shadow: 0px 0px 2px colors.$white; text-align: left; } @@ -703,7 +704,7 @@ blockquote { } .pee-page .ui.styled.accordion { width: 100%; - background: #eee; + background: colors.$grey75; } .pee-page .accordion .title { text-align: right; diff --git a/public/css/sass/components/pages/CattoolPage.scss b/public/css/sass/components/pages/CattoolPage.scss index f9def1d3f2..116ef349d8 100644 --- a/public/css/sass/components/pages/CattoolPage.scss +++ b/public/css/sass/components/pages/CattoolPage.scss @@ -8,7 +8,6 @@ @use '../../mbc-style'; @use '../../lexiqa'; @use '../segment/SegmentFooterTabMessages'; -@use '../MarkAsCompleteButton'; @use '../header/segmentsFilter'; @use '../ReviewExtendedPanel'; //components diff --git a/public/css/sass/components/pages/DashboardPage.scss b/public/css/sass/components/pages/DashboardPage.scss index 77703e526f..72b14d0eb9 100644 --- a/public/css/sass/components/pages/DashboardPage.scss +++ b/public/css/sass/components/pages/DashboardPage.scss @@ -19,4 +19,6 @@ @use '../UserProjectDropdown'; @use '../signin/OnBoarding'; @use '../MembersFilter'; +@use '../Projects/ProjectContainer.scss'; +@use '../Projects/JobContainer.scss'; @use '../ProjectBulkActions'; diff --git a/public/css/sass/components/pages/NewProjectPage.scss b/public/css/sass/components/pages/NewProjectPage.scss index 1d25a74fc0..1d36ac1995 100644 --- a/public/css/sass/components/pages/NewProjectPage.scss +++ b/public/css/sass/components/pages/NewProjectPage.scss @@ -16,6 +16,7 @@ @use '../SettingsPanel'; @use '../../commons/colors'; +@use '../../commons/variables'; @use '../UploadFile'; .new_project__page { @@ -34,7 +35,8 @@ .translation-options, #additional-input-params { display: flex; - justify-content: center; + justify-content: space-between; + align-items: center; } .translation-options { @@ -45,12 +47,12 @@ opacity: 0.4; h2, label { - color: colors.$grey1; + color: colors.$grey500; } input, .select-with-icon__wrapper .select { cursor: not-allowed; - background-color: colors.$grey9; + background-color: colors.$grey75; } } } @@ -63,7 +65,7 @@ } .label-tmx-select > span:last-of-type { - color: colors.$linkBlue; + color: colors.$blue700; &[aria-label]::after { min-width: 260px; white-space: normal; @@ -87,20 +89,11 @@ } } -.wrapper-upload .upload-box-not-logged, .upload-waiting-logged { - border: 1px dashed #ccc; - margin: 18px 0; - min-height: 200px; - -moz-border-radius: 4px; - border-radius: 4px; - background: #fff; - display: flex; - flex-direction: column; - justify-content: center; align-items: stretch; - text-align: center; - gap: 12px; +} +.wrapper-upload .upload-box-not-logged, +.upload-waiting-logged { .upload-loading { background: url(/public/img/loading.gif) 47% 50% no-repeat !important; background-size: 24px !important; @@ -114,7 +107,7 @@ } } span { - color: colors.$grey6; + color: colors.$grey700; font-size: 24px; line-height: 20px; } @@ -152,11 +145,9 @@ .upload-input { padding: 3px 5px 3px 9px; font-size: 16px !important; - -moz-border-radius: 2px; - border-radius: 2px; + border-radius: variables.$border-radius-default; border: 1px solid rgba(34, 36, 38, 0.15); - height: 36px; - box-shadow: inset 0 1px 3px #ddd; + height: 40px; } } @@ -264,7 +255,7 @@ } } -@media only screen and (max-width: 1320px) { +@media only screen and (max-width: 1400px) { .translate-box.tmx-select, .translate-box.source, .translate-box.target, @@ -377,9 +368,10 @@ } } -@media only screen and (max-width: 1279px) { +@media only screen and (max-width: 1300px) { .translation-row .translation-options { flex-wrap: wrap; + justify-content: center; } .wrapper-upload { .translate-box { diff --git a/public/css/sass/components/pages/QualityReportPage.scss b/public/css/sass/components/pages/QualityReportPage.scss index 9e8d77a22c..e5a2a3889c 100644 --- a/public/css/sass/components/pages/QualityReportPage.scss +++ b/public/css/sass/components/pages/QualityReportPage.scss @@ -11,7 +11,8 @@ @use '../header/header'; @use '../header/ActionMenu'; @use '../../style'; -@use "../../commons/colors"; +@use '../../commons/colors'; +@use '../../commons/variables'; $color-red: #fb2a0d; $color-orange: #fbaa0d; @@ -21,7 +22,7 @@ $color-yellow: #ffe600; body { font-family: Calibri, Arial, Helvetica, sans-serif; text-align: left; - background: colors.$grey5; + background: colors.$grey50; font-size: 16px; min-width: 1024px; overflow-x: auto; @@ -32,7 +33,7 @@ header { min-width: 1024px; .nav-bar { width: 100%; - background: #002b5c !important; + background: colors.$blue900 !important; .logo { /*left: 13px;*/ margin: 0; @@ -40,7 +41,7 @@ header { .header-project-container-info { width: 75%; /*background: #00123a;*/ - color: #fff; + color: colors.$white; margin-top: 9px; height: 47px; .header-project-info { @@ -66,10 +67,10 @@ header { } .header-assignee { margin-left: 20px; - border: 1px solid #676767; + border: 1px solid colors.$grey700; padding: 1px 12px 1px 3px; border-radius: 20px; - background: #676767; + background: colors.$grey700; display: flex; align-items: center; flex-wrap: nowrap; @@ -97,7 +98,7 @@ header { background: transparent; color: white; &:hover { - background: #676767; + background: colors.$grey700; } i { font-size: 20px; @@ -128,50 +129,60 @@ header { transition: 0.3s ease; .qr-bg-head { height: 258px; - background: colors.$grey5; + background: colors.$grey50; position: absolute; width: 100%; z-index: -1; } .ui.table thead th { - background: #fff; + background: colors.$white; border: none; - border-bottom: 1px solid #f2f4f7; + border-bottom: 1px solid colors.$grey50; border-radius: 0; } .ui.celled.table tr th, .ui.celled.table tr td { - border-left: 1px solid #f2f4f7; + border-left: 1px solid colors.$grey50; border-radius: 0; } - .qr-job-summary { - max-width: 1366px; - min-width: 1024px; - margin: 0 auto; - padding: 20px 15px 0; - h3 { + .layout__container { + padding: 30px 0; + h6 { } .qr-label { font-weight: 100; - font-size: 14px; + font-size: 12px; line-height: 12px; padding-right: 9px; } + .qr-info { + font-size: 14px; + } .qr-production-quality { + .qr-production-container { + display: flex; + gap: 16px; + } .qr-production { display: flex; - background: colors.$grey3; - justify-content: space-between; - width: 100%; - padding-left: 15px; + background: colors.$grey150; + padding: 0 24px; align-items: center; position: relative; + height: 64px; + gap: 30px; + border-radius: variables.$border-radius-default; + flex: 1 0 0; .job-id { - font-size: 14px; + font-size: 16px; + min-width: 90px; + color: colors.$grey700; + line-height: 24px; } .source-to-target { display: flex; align-items: center; + min-width: 100px; .qr-to { display: flex; i { @@ -184,182 +195,173 @@ header { .progress-percent { display: flex; align-items: center; - .progress-bar { - margin: 0; - min-width: 130px; - } - .percent { - padding-left: 5px; + gap: 8px; + + .job-progress-bar { + min-width: 160px; } } - .qr-effort { - padding: 15px 0; - &:last-child { - padding-right: 15px !important; + .qr-effort-container { + display: flex; + padding-left: 16px; + justify-content: flex-end; + align-items: center; + gap: 16px; + } + } + .qr-effort { + padding: 15px 0; + &:last-child { + padding-right: 15px !important; + } + &.translator { + max-width: 95px; + b { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; } - &.translator { - max-width: 15%; - min-width: 30px; - b { - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; + } + &.qr-score { + display: flex; + width: 200px; + height: 64px; + padding: 12px; + justify-content: space-between; + gap: 8px; + flex-shrink: 0; + background: colors.$grey150; + border-radius: variables.$border-radius-default; + > div { + display: flex; + flex-direction: column; + justify-content: space-between; + align-items: flex-start; + align-self: stretch; + &:last-child { + align-items: flex-end; } } - &.qr-score { - padding: 15px 25px; - .qr-tolerated-score, - .qr-pass-score { - font-size: 20px; - } - .qr-info { - flex-direction: column; - align-items: unset; - } + .qr-ept-info { + display: flex; + align-items: center; + gap: 4px; + font-size: 12px; + line-height: 12px; + font-weight: 700; } - - &.qr-pass { - background: colors.$greenDefaultTransparent; + .qr-tolerated-score { + font-size: 24px; + font-weight: 700; + line-height: 14px; } - &.qr-fail { - background: colors.$redDefaultTransparent; + .qr-info { + flex-direction: column; + align-items: unset; } - &.qr-pass, - &.qr-fail, - &.qr-norevision { - margin-right: -1px; - .qr-info { - display: flex; - flex-direction: row; - align-items: center; - .qr-tolerated-score { - font-size: 42px; - margin-right: 10px; - } - } - .qr-label { - text-decoration: underline; - cursor: pointer; - width: fit-content; - padding-right: 8px; - &:hover { - text-decoration: none; - } - &:first-child { - text-decoration: none; - } + .qr-pass-score { + font-size: 16px; + font-weight: 700; + line-height: 16px; + } + .qr-threshold { + font-size: 12px; + line-height: 12px; + } + &.qr-pass { + background: #{rgba(colors.$green500, 0.2)}; + .qr-pass-score { + color: colors.$green500; + font-weight: 700; } } - .qr-info { - display: flex; - align-items: center; - justify-content: space-between; + &.qr-fail { + background: #{rgba(colors.$red500, 0.2)}; + .qr-pass-score { + color: colors.$red500; + font-weight: 700; + } } } } .qr-quality { margin-top: 20px; margin-bottom: 20px; - border-bottom: 2px solid colors.$grey4; + border: 1px solid colors.$grey150; position: relative; z-index: 1; + border-radius: variables.$border-radius-default; + overflow: hidden; + font-size: 14px; .qr-head { display: flex; align-items: center; font-weight: 700; - background: colors.$grey4; + background: colors.$grey150; + height: 40px; .qr-title { - text-align: center; - text-transform: capitalize; - &:first-child { - text-align: left; - } + padding-left: 24px; } } .qr-body-list { display: flex; - &:not(.severity_weight-line) { - &:not(.qr-body-list-first) { - border-left: 2px solid colors.$grey4; - border-right: 2px solid colors.$grey4; - border-top: 2px solid colors.$grey4; - } - - .qr-element { - border-left: 1px solid colors.$grey4; - } + align-items: center; + background-color: colors.$white; + height: 40px; + border-bottom: 1px solid colors.$grey100; + &:last-child { + border-bottom: none; } .qr-element { - background: white; position: relative; - &.empty { - background: colors.$grey4; - } - &:first-child { - border: none; - display: flex; - justify-content: center; - flex-direction: column; - } - &.severity_weight { - background: colors.$grey5 !important; - } - span { - top: 50%; - position: absolute; - transform: translateY(-50%); - } + padding-left: 24px; } &.severity_weight-line { + background-color: colors.$grey50; + height: 32px; + font-weight: 700; + span { + font-weight: 400; + color: colors.$grey700; + } .qr-element { - padding: 2px 15px; font-size: 14px; + height: 100%; + line-height: 32px; + } + } + &.qr-total-line { + background-color: colors.$grey150; + height: 40px; + .qr-issue-name, + .total-score { + font-weight: 700; + line-height: 40px; + } + .total-score { + background-color: colors.$grey300; + height: 100%; } } } - .qr-title, - .qr-element { - padding: 10px 15px; + .qr-issue { + font-weight: 700; } .qr-issue, .qr-issue-name { width: 56%; - font-weight: 500; - font-size: 15px; } .qr-severity, .severity { width: 21%; - text-align: center; + text-align: left; } .qr-total-severity, .total-severity { width: 20%; - background: colors.$grey1; - } - .qr-total-severity { - padding: 20px 15px; - &.job-not-passed { - background-color: #fb590d; - } - &.job-passed { - background-color: #83fd97; - &.qr-old { - background-color: #83fd97; - display: unset; - } - } - &.qr-old { - background: inherit; - display: unset; - } - .qr-info.qr-info-total { - font-size: 20px; - } } .total-severity { - text-align: center; &.job-not-passed { background-color: rgba(255, 123, 35, 0.31); text-align: center; @@ -373,7 +375,7 @@ header { &.kudos-total { display: flex; flex-direction: column; - background: colors.$grey3; + background: colors.$grey150; font-weight: 700; text-transform: capitalize; } @@ -381,34 +383,54 @@ header { } } .qr-header { - height: 70px; + margin-bottom: 26px; h3 { - font-size: 22px; + font-size: 24px; font-weight: bold; + line-height: 24px; } .filter-dropdown .dropdown { font-size: 20px !important; max-width: 190px; } } + .qr-kudos { + width: 100%; + display: flex; + justify-content: space-between; + background-color: colors.$white; + padding: 0 24px; + height: 40px; + align-items: center; + border-radius: variables.$border-radius-default; + margin-bottom: 20px; + border: 1px solid colors.$grey150; + font-size: 14px; + .qr-kudos-value { + padding-right: 140px; + } + } .qr-feedback-container { min-height: 73px; position: relative; margin-bottom: 20px; + background-color: colors.$white; + border-radius: variables.$border-radius-default; + overflow: hidden; .qr-feedback { .qr-head { padding: 10px 20px; - background: colors.$grey4; + background: colors.$grey150; .label.revision-color { float: left; margin-right: 10px; margin-top: 5px; &.revision-1 { - background: #2fb177; + background: colors.$green800; } &.revision-2 { - background: #9352c1; + background: colors.$purple500; } } } @@ -426,9 +448,19 @@ header { align-items: center; } .qr-segment-details-container { - background: colors.$grey4; - padding: 35px 15px 15px; + background: colors.$grey100; + padding: 16px; + border-radius: variables.$border-radius-default; + border: 1px solid colors.$grey150; .qr-segments-summary { + .document-name { + display: flex; + align-items: center; + font-size: 14px; + margin-top: 8px; + line-height: 16px; + gap: 8px; + } h3 { margin-bottom: 0; } @@ -439,22 +471,26 @@ header { } .qr-segments-list { .qr-single-segment { - padding-top: 30px; + margin-top: 30px; + border-radius: variables.$border-radius-default; + overflow: hidden; + border: 1px solid colors.$grey150; &:first-child { - padding-top: 15px; + margin-top: 15px; } .qr-segment-head { display: flex; position: relative; - background: #fff; + background: colors.$grey50; align-items: center; + height: 48px; + padding: 0 24px; + font-size: 14px; .segment-id { - width: 18%; - padding: 15px 0.78571429em; + width: 20%; } .segment-production-container { width: 68%; - padding: 15px 0.78571429em; display: flex; justify-content: space-between; align-items: center; @@ -468,44 +504,52 @@ header { } } .segment-status-container { - width: 14%; - padding: 15px 0.78571429em; - .status-new { - font-size: 20px; - color: #8b8e92; - } - .status-translated { - font-size: 20px; - color: colors.$translatedBlue; - } - .status-approved { - font-size: 20px; - color: colors.$approvedGreen; - &.approved-r2 { - color: colors.$approved2Green; - } - } - .status-approved2 { - color: colors.$approved2Green; - font-size: 20px; - } - .status-draft { - font-size: 20px; - color: colors.$grey1; - } - .status-rejected { - font-size: 20px; - color: colors.$rebuttedRed; - } - } + width: 18%; + display: flex; + align-items: center; + justify-content: flex-end; + .qr-info { + font-size: 14px; + text-transform: capitalize; + } + //.status-new { + // font-size: 20px; + // color: colors.$grey500; + //} + //.status-translated { + // font-size: 20px; + // color: colors.$blue500; + //} + //.status-approved { + // font-size: 20px; + // color: colors.$green800; + // &.approved-r2 { + // color: colors.$purple500; + // } + //} + //.status-approved2 { + // color: colors.$purple500; + // font-size: 20px; + //} + //.status-draft { + // font-size: 20px; + // color: colors.$grey500; + //} + //.status-rejected { + // font-size: 20px; + // color: colors.$orange600; + //} + } .qr-segment-body { - border-bottom: 1px solid colors.$grey2; - border-left: 1px solid colors.$grey2; - border-right: 1px solid colors.$grey2; .segment-container { display: flex; - background: colors.$grey3; + background: colors.$white; + border-bottom: 1px solid colors.$grey100; + height: 40px; + font-size: 14px; + align-items: center; &.qr-issues { + min-height: 48px !important; .qr-text { width: 80%; } @@ -516,19 +560,34 @@ header { .segment-content { display: flex; align-items: center; - padding: 10px 0.78571429em; - margin-top: 1px; + + padding: 0 24px; + + align-content: center; .tte { max-width: 110px; font-weight: bold; } } + &.qr-issues { + background-color: colors.$grey50 !important; + border-bottom: none !important; + height: unset; + padding-right: 24px; + .segment-content { + background-color: colors.$grey50 !important; + } + .qr-text { + padding: 4px 0; + } + } .qr-segment-title { - width: 20%; - background: colors.$grey5; + min-width: 20%; justify-content: space-between; - + .buttons.segment-production { + margin-left: 16px; + } button { width: 22px; height: 22px; @@ -545,17 +604,17 @@ header { margin: 0; } &:hover { - background: #e8e9ef; + background: colors.$grey100; i { - color: #000000; + color: colors.$black; } } &.active, &:active, &:hover { - background: #e8e9ef; + background: colors.$grey100; i { - color: #000000; + color: colors.$black; } } } @@ -571,17 +630,17 @@ header { } &.qr-translated { b { - color: colors.$translatedBlue; + color: colors.$blue500; } } &.qr-revised { b { - color: colors.$approvedGreen; + color: colors.$green800; } } &.qr-revised-2ndpass { b { - color: colors.$approved2Green; + color: colors.$purple500; } } &.rtl-lang { @@ -595,14 +654,8 @@ header { background: colors.$white; margin-right: 1px; display: inline-block; - color: #5f5f5f; - .added { - background: rgba(158, 255, 0, 0.5); - } - .deleted { - background: rgba(255, 46, 0, 0.3); - text-decoration: line-through; - } + + .qr-issues-list { display: flex; flex-wrap: wrap; @@ -614,36 +667,30 @@ header { padding: 3px 10px; margin-right: 5px; margin-top: 5px; - background: colors.$grey4; - + background: colors.$white; + border: 1px solid colors.$grey100; + border-radius: variables.$border-radius-default; + gap: 6px; &.automated { - padding: 0; - padding-right: 5px; .box-icon { display: flex; - padding: 5px 3px 5px 5px; - background: colors.$grey5; + background: colors.$grey50; margin-right: 6px; &.error { - color: colors.$red800; + color: colors.$red400; } &.warning { - color: colors.$orangeDefault; + color: colors.$orange200; } } } - .qr-error { - } - .qr-severity { - margin-left: 5px; - } .qr-comment-list { padding: 5px 10px; font-size: 14px; - background: #ffffff; - color: #787878; + background: colors.$white; + color: colors.$grey600; box-shadow: - 0 0 0 #e0e0e0, + 0 0 0 colors.$grey200, 0 0 2px rgba(0, 0, 0, 0.12), 0 2px 4px rgba(0, 0, 0, 0.24) !important; max-height: 300px; @@ -653,17 +700,17 @@ header { font-size: 16px; margin-bottom: 0; .re-revisor { - color: colors.$approvedGreen; + color: colors.$green800; } .re-revisor2 { - color: colors.$approved2Green; + color: colors.$purple500; } .re-translator { - color: colors.$translatedBlue; + color: colors.$blue500; } .re-comment-date { font-size: 13px; - color: colors.$grey1; + color: colors.$grey500; } } } @@ -673,19 +720,16 @@ header { .qr-spec { width: 14%; justify-content: space-between; - background: #ffffff; + background: colors.$white; .spec-words { } .tm-percent { - background: #0abeed; - color: #ffffff; padding: 0 3px; font-size: 16px; - } - .per-yellow { - padding: 0 3px; - background: #ffcc00 !important; - color: #333 !important; + width: 100%; + .badge-container { + width: 100%; + } } } } @@ -693,15 +737,11 @@ header { .segment-container { box-shadow: none !important; .segment-content { - background: colors.$grey5; .qr-issues-list { .qr-issue { - background: #ffffff; + background: colors.$white; } } - &.qr-text { - border-left: 1px solid #e8e9ec; - } } &.shadow-1 { position: relative; @@ -709,12 +749,109 @@ header { background: colors.$white; } .qr-segment-title { - background: colors.$grey4; + background: colors.$grey100; flex-shrink: 0; + height: 100%; + } + } + } + } + .qr-history { + display: flex; + flex-direction: column; + border-top: 1px solid colors.$grey100; + font: variables.$font-style-small; + .qr-history-item { + display: flex; + min-height: 40px; + align-items: center; + align-self: stretch; + background-color: colors.$grey50; + padding: 8px 0; + padding-right: 24px; + } + .qr-history-status { + display: flex; + width: 173px; + padding: 0 4px 0 24px; + align-items: center; + gap: 8px; + align-self: stretch; + font-weight: 700; + position: relative; + &.qr-history-status_translated { + .qr-history-status_point,.qr-history-status_separator { + background-color: colors.$translatedBlue; + } + color: colors.$translatedBlue; + } + &.qr-history-status_approved { + .qr-history-status_point,.qr-history-status_separator { + background-color: colors.$approvedGreen; } + color: colors.$approvedGreen; + } + &.qr-history-status_approved2 { + .qr-history-status_point , .qr-history-status_separator{ + background-color: colors.$approved2Green; + } + color: colors.$approved2Green; + } + .qr-history-status_point { + width: 8px; + height: 8px; + flex-shrink: 0; + aspect-ratio: 1/1; + border-radius: 8px; + } + .qr-history-status_separator { + width: 1px; + height: 24px; + position: absolute; + border-radius: 8px; + bottom: -20px; + left: 27px; + } + } + .qr-history-date { + display: flex; + width: 147px; + flex-direction: column; + justify-content: center; + align-items: flex-start; + gap: 24px; + align-self: stretch; + } + .qr-history-version { + display: inline-block; + padding: 0 24px; + flex-direction: column; + justify-content: center; + align-items: flex-start; + gap: 24px; + flex: 1 0 0; + align-self: stretch; + } + .qr-history-issue { + font-weight: 700; + span { + font-weight: 400; } } + .badge-container { + cursor: pointer; + } + } + .added { + background: rgba(18, 230, 130, 0.12); + color: colors.$green1000 } + .deleted { + background: rgba(255, 46, 0, 0.3); + color: colors.$red600; + text-decoration: line-through; + } + } } } @@ -727,6 +864,7 @@ header { padding: 9px 46px 9px 12px; border-radius: 40px; height: 38px; + line-height: 20px; } li.dropdown__option { padding: 8px; @@ -738,9 +876,12 @@ header { font-size: 16px; } .custom-dropdown.select__dropdown { - background-color: #fff; + background-color: colors.$white; min-width: 120px; } + .filter-category { + max-width: 200px; + } .filter-category .select__dropdown-wrapper { width: unset; } @@ -751,36 +892,53 @@ header { } } } -.qr-reviewType-dropdown, .filter-reviewType { +.qr-reviewType-control { + width: 200px; + .segmented-control { + background-color: colors.$black100; + } + .segmented-control__cursor:before { + background-color: colors.$white; + border-radius: variables.$border-radius-default; + } + .segmented-control input:checked + .segmented-control__label { + color: colors.$black; + } + .segmented-control__label { + line-height: 40px; + } +} +.qr-reviewType-dropdown, +.filter-reviewType { .circular.label { &.new-color { box-shadow: 0px 0px 0px 1px rgba(34, 36, 38, 0.25) inset; - background: #ffffff; + background: colors.$white; } &.draft-color { - background: colors.$grey1; + background: colors.$grey500; } &.translated-color { - background: colors.$translatedBlue; + background: colors.$blue500; } &.approved-color { - background: colors.$approvedGreen; + background: colors.$green800; } &.rejected-color { - background: colors.$rebuttedRed; + background: colors.$orange600; } &.revision-color { - background: colors.$approvedGreen; + background: colors.$green800; } &.second-revision-color, &.approved-2ndpass-color { - background: colors.$approved2Green; + background: colors.$purple500; } } } @@ -789,9 +947,11 @@ header { display: flex; align-items: center; box-sizing: border-box; + gap: 8px; .filter-dropdown { display: flex; align-items: center; + gap: 8px; button { height: auto; width: auto; @@ -800,9 +960,6 @@ header { .dropdown { background: colors.$white !important; } - &:nth-child(2) { - margin-left: 15px; - } .ui.basic.button { font-family: 'calibri', Arial, Helvetica, sans-serif; font-size: 16px !important; @@ -824,24 +981,21 @@ header { .ui.cancel.label { position: absolute; padding: 4px; - background-color: #d6d6d6; + background-color: colors.$grey200; border-radius: 15px; top: 8px; line-height: 0px; right: 0px; visibility: hidden; &:hover { - background-color: #cccccc !important; + background-color: colors.$grey200 !important; } } - .filter-category { - margin-left: 5px; - } .not-filtered { .ui.basic.button { &:hover { - box-shadow: 0px 0px 0px 1px colors.$translatedBlue inset; - color: colors.$translatedBlue !important; + box-shadow: 0px 0px 0px 1px colors.$blue500 inset; + color: colors.$blue500 !important; } &.disabled { box-shadow: 0 0 0 1px rgba(34, 36, 38, 0.25) inset !important; @@ -851,12 +1005,12 @@ header { } .filtered { .ui.basic.button { - background-color: #ffffff !important; + background-color: colors.$white !important; box-shadow: - 0 0 0 #e0e0e0, + 0 0 0 colors.$grey200, 0 0 2px rgba(0, 0, 0, 0.12), 0 2px 4px rgba(0, 0, 0, 0.24) !important; - color: #000000 !important; + color: colors.$black !important; padding: 9px 20px 9px 15px; &:hover { width: fit-content; @@ -874,13 +1028,13 @@ header { .ui.basic.button { background: transparent none !important; box-shadow: - 0 0 0 #e0e0e0, + 0 0 0 colors.$grey200, 0 0 2px rgba(0, 0, 0, 0.12), 0 2px 4px rgba(0, 0, 0, 0.24) !important; - color: #000000 !important; + color: colors.$black !important; padding: 9px 20px 9px 15px; &:hover { - background-color: #ffffff !important; + background-color: colors.$white !important; .ui.cancel.label { visibility: unset; right: 5px; @@ -904,11 +1058,11 @@ header { float: none; label { &:before { - background: #dcdfe4 !important; + background: colors.$grey150 !important; } &:after { box-shadow: inset 0 0 0 1px rgba(34, 36, 38, 0.25); - background: #ffffff; + background: colors.$white; } } } @@ -957,7 +1111,7 @@ header { } .clear-filter-element { margin-left: 13px; - border-left: 1px solid #d6d6d7; + border-left: 1px solid colors.$grey200; padding-left: 13px; color: black; display: flex; @@ -985,7 +1139,7 @@ header { .no-segments-found { text-align: center; margin: 15px 0; - border: 1px dashed #c3c8d0; + border: 1px dashed colors.$grey200; padding: 15px; } @@ -993,38 +1147,38 @@ header { margin: 30px 15px 15px; z-index: 1; .ui.active.inverted.dimmer { - background: colors.$grey4; + background: colors.$grey100; } } .per-orange { - background: colors.$rebuttedRed !important; - color: #fff !important; + background: colors.$orange600 !important; + color: colors.$white !important; } .per-blue { - background: colors.$translatedBlue !important; - color: #fff !important; + background: colors.$blue500 !important; + color: colors.$white !important; } .per-green { - background: colors.$approvedGreen !important; - color: #fff !important; + background: colors.$green800 !important; + color: colors.$white !important; } .per-yellow { - background: #ffcc00 !important; - color: #333 !important; + background: colors.$orange200 !important; + color: colors.$grey1300 !important; } .per-red { - background: colors.$redDefault !important; - color: #fff !important; + background: colors.$red500 !important; + color: colors.$white !important; } .per-gray { - background: #aaa !important; - color: colors.$grey1 !important; + background: colors.$grey400 !important; + color: colors.$grey500 !important; } .ui.popup.bottom.right.qr-score-popup { diff --git a/public/css/sass/components/segment/Editor.scss b/public/css/sass/components/segment/Editor.scss index 73d8f1b6b7..2f12a0c766 100644 --- a/public/css/sass/components/segment/Editor.scss +++ b/public/css/sass/components/segment/Editor.scss @@ -1,3 +1,4 @@ +@use '../../commons/colors'; /** * Draft v0.11.7 * @@ -6,4 +7,4 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ -.DraftEditor-editorContainer,.DraftEditor-root,.public-DraftEditor-content{height:inherit;text-align:initial}.public-DraftEditor-content[contenteditable=true]{-webkit-user-modify:read-write-plaintext-only}.DraftEditor-root{position:relative}.DraftEditor-editorContainer{background-color:rgba(255,255,255,0);border-left:.1px solid transparent;position:relative;z-index:1}.public-DraftEditor-block{position:relative}.DraftEditor-alignLeft .public-DraftStyleDefault-block{text-align:left}.DraftEditor-alignLeft .public-DraftEditorPlaceholder-root{left:0;text-align:left}.DraftEditor-alignCenter .public-DraftStyleDefault-block{text-align:center}.DraftEditor-alignCenter .public-DraftEditorPlaceholder-root{margin:0 auto;text-align:center;width:100%}.DraftEditor-alignRight .public-DraftStyleDefault-block{text-align:right}.DraftEditor-alignRight .public-DraftEditorPlaceholder-root{right:0;text-align:right}.public-DraftEditorPlaceholder-root{color:#9197a3;position:absolute;width:100%;z-index:1}.public-DraftEditorPlaceholder-hasFocus{color:#bdc1c9}.DraftEditorPlaceholder-hidden{display:none}.public-DraftStyleDefault-block{position:relative;white-space:pre-wrap}.public-DraftStyleDefault-ltr{direction:ltr;text-align:left}.public-DraftStyleDefault-rtl{direction:rtl;text-align:right}.public-DraftStyleDefault-listLTR{direction:ltr}.public-DraftStyleDefault-listRTL{direction:rtl}.public-DraftStyleDefault-ol,.public-DraftStyleDefault-ul{margin:16px 0;padding:0}.public-DraftStyleDefault-depth0.public-DraftStyleDefault-listLTR{margin-left:1.5em}.public-DraftStyleDefault-depth0.public-DraftStyleDefault-listRTL{margin-right:1.5em}.public-DraftStyleDefault-depth1.public-DraftStyleDefault-listLTR{margin-left:3em}.public-DraftStyleDefault-depth1.public-DraftStyleDefault-listRTL{margin-right:3em}.public-DraftStyleDefault-depth2.public-DraftStyleDefault-listLTR{margin-left:4.5em}.public-DraftStyleDefault-depth2.public-DraftStyleDefault-listRTL{margin-right:4.5em}.public-DraftStyleDefault-depth3.public-DraftStyleDefault-listLTR{margin-left:6em}.public-DraftStyleDefault-depth3.public-DraftStyleDefault-listRTL{margin-right:6em}.public-DraftStyleDefault-depth4.public-DraftStyleDefault-listLTR{margin-left:7.5em}.public-DraftStyleDefault-depth4.public-DraftStyleDefault-listRTL{margin-right:7.5em}.public-DraftStyleDefault-unorderedListItem{list-style-type:square;position:relative}.public-DraftStyleDefault-unorderedListItem.public-DraftStyleDefault-depth0{list-style-type:disc}.public-DraftStyleDefault-unorderedListItem.public-DraftStyleDefault-depth1{list-style-type:circle}.public-DraftStyleDefault-orderedListItem{list-style-type:none;position:relative}.public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-listLTR:before{left:-36px;position:absolute;text-align:right;width:30px}.public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-listRTL:before{position:absolute;right:-36px;text-align:left;width:30px}.public-DraftStyleDefault-orderedListItem:before{content:counter(ol0) ". ";counter-increment:ol0}.public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-depth1:before{content:counter(ol1,lower-alpha) ". ";counter-increment:ol1}.public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-depth2:before{content:counter(ol2,lower-roman) ". ";counter-increment:ol2}.public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-depth3:before{content:counter(ol3) ". ";counter-increment:ol3}.public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-depth4:before{content:counter(ol4,lower-alpha) ". ";counter-increment:ol4}.public-DraftStyleDefault-depth0.public-DraftStyleDefault-reset{counter-reset:ol0}.public-DraftStyleDefault-depth1.public-DraftStyleDefault-reset{counter-reset:ol1}.public-DraftStyleDefault-depth2.public-DraftStyleDefault-reset{counter-reset:ol2}.public-DraftStyleDefault-depth3.public-DraftStyleDefault-reset{counter-reset:ol3}.public-DraftStyleDefault-depth4.public-DraftStyleDefault-reset{counter-reset:ol4} \ No newline at end of file +.DraftEditor-editorContainer,.DraftEditor-root,.public-DraftEditor-content{height:inherit;text-align:initial}.public-DraftEditor-content[contenteditable=true]{-webkit-user-modify:read-write-plaintext-only}.DraftEditor-root{position:relative}.DraftEditor-editorContainer{background-color:rgba(255,255,255,0);border-left:.1px solid transparent;position:relative;z-index:1}.public-DraftEditor-block{position:relative}.DraftEditor-alignLeft .public-DraftStyleDefault-block{text-align:left}.DraftEditor-alignLeft .public-DraftEditorPlaceholder-root{left:0;text-align:left}.DraftEditor-alignCenter .public-DraftStyleDefault-block{text-align:center}.DraftEditor-alignCenter .public-DraftEditorPlaceholder-root{margin:0 auto;text-align:center;width:100%}.DraftEditor-alignRight .public-DraftStyleDefault-block{text-align:right}.DraftEditor-alignRight .public-DraftEditorPlaceholder-root{right:0;text-align:right}.public-DraftEditorPlaceholder-root{color:colors.$grey400;position:absolute;width:100%;z-index:1}.public-DraftEditorPlaceholder-hasFocus{color:colors.$grey300}.DraftEditorPlaceholder-hidden{display:none}.public-DraftStyleDefault-block{position:relative;white-space:pre-wrap}.public-DraftStyleDefault-ltr{direction:ltr;text-align:left}.public-DraftStyleDefault-rtl{direction:rtl;text-align:right}.public-DraftStyleDefault-listLTR{direction:ltr}.public-DraftStyleDefault-listRTL{direction:rtl}.public-DraftStyleDefault-ol,.public-DraftStyleDefault-ul{margin:16px 0;padding:0}.public-DraftStyleDefault-depth0.public-DraftStyleDefault-listLTR{margin-left:1.5em}.public-DraftStyleDefault-depth0.public-DraftStyleDefault-listRTL{margin-right:1.5em}.public-DraftStyleDefault-depth1.public-DraftStyleDefault-listLTR{margin-left:3em}.public-DraftStyleDefault-depth1.public-DraftStyleDefault-listRTL{margin-right:3em}.public-DraftStyleDefault-depth2.public-DraftStyleDefault-listLTR{margin-left:4.5em}.public-DraftStyleDefault-depth2.public-DraftStyleDefault-listRTL{margin-right:4.5em}.public-DraftStyleDefault-depth3.public-DraftStyleDefault-listLTR{margin-left:6em}.public-DraftStyleDefault-depth3.public-DraftStyleDefault-listRTL{margin-right:6em}.public-DraftStyleDefault-depth4.public-DraftStyleDefault-listLTR{margin-left:7.5em}.public-DraftStyleDefault-depth4.public-DraftStyleDefault-listRTL{margin-right:7.5em}.public-DraftStyleDefault-unorderedListItem{list-style-type:square;position:relative}.public-DraftStyleDefault-unorderedListItem.public-DraftStyleDefault-depth0{list-style-type:disc}.public-DraftStyleDefault-unorderedListItem.public-DraftStyleDefault-depth1{list-style-type:circle}.public-DraftStyleDefault-orderedListItem{list-style-type:none;position:relative}.public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-listLTR:before{left:-36px;position:absolute;text-align:right;width:30px}.public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-listRTL:before{position:absolute;right:-36px;text-align:left;width:30px}.public-DraftStyleDefault-orderedListItem:before{content:counter(ol0) ". ";counter-increment:ol0}.public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-depth1:before{content:counter(ol1,lower-alpha) ". ";counter-increment:ol1}.public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-depth2:before{content:counter(ol2,lower-roman) ". ";counter-increment:ol2}.public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-depth3:before{content:counter(ol3) ". ";counter-increment:ol3}.public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-depth4:before{content:counter(ol4,lower-alpha) ". ";counter-increment:ol4}.public-DraftStyleDefault-depth0.public-DraftStyleDefault-reset{counter-reset:ol0}.public-DraftStyleDefault-depth1.public-DraftStyleDefault-reset{counter-reset:ol1}.public-DraftStyleDefault-depth2.public-DraftStyleDefault-reset{counter-reset:ol2}.public-DraftStyleDefault-depth3.public-DraftStyleDefault-reset{counter-reset:ol3}.public-DraftStyleDefault-depth4.public-DraftStyleDefault-reset{counter-reset:ol4} \ No newline at end of file diff --git a/public/css/sass/components/segment/Glossary.scss b/public/css/sass/components/segment/Glossary.scss index 1ffcbb2fd6..bef78d851f 100644 --- a/public/css/sass/components/segment/Glossary.scss +++ b/public/css/sass/components/segment/Glossary.scss @@ -4,20 +4,20 @@ display: inline-block; position: relative; background: rgba(255, 169, 2, 0.24); - border-bottom: 2px solid #ffa902; + border-bottom: 2px solid colors.$orange400; cursor: pointer; } .glossaryItem { display: inline-block; position: relative; - border-bottom: 2px solid colors.$translatedBlue; + border-bottom: 2px solid colors.$blue500; cursor: pointer; } .blacklistItem { background: rgba(255, 47, 34, 0.24); - border-bottom: 2px solid #ff2f22; + border-bottom: 2px solid colors.$red500; display: inline-block; position: relative; } diff --git a/public/css/sass/components/segment/IcuHighlight.scss b/public/css/sass/components/segment/IcuHighlight.scss index 71f1bca38d..ba5f3e4721 100644 --- a/public/css/sass/components/segment/IcuHighlight.scss +++ b/public/css/sass/components/segment/IcuHighlight.scss @@ -4,9 +4,9 @@ .icuItem { display: inline-block; position: relative; - color: colors.$linkBlue; + color: colors.$blue700; &.icuItem-error { - color: colors.$redDefault; + color: colors.$red500; cursor: pointer; } } diff --git a/public/css/sass/components/segment/SegmentFooterTabMessages.scss b/public/css/sass/components/segment/SegmentFooterTabMessages.scss index 5ee92cab92..d0d93fec45 100644 --- a/public/css/sass/components/segment/SegmentFooterTabMessages.scss +++ b/public/css/sass/components/segment/SegmentFooterTabMessages.scss @@ -1,3 +1,4 @@ +@use '../../commons/colors'; div.segment-notes ul.graysmall li { width: 90%; } @@ -18,7 +19,7 @@ div.segment-notes ul.graysmall li span.note-label { box-sizing: border-box; position: relative; border: 5px solid white; - border-right: 1px solid #ccc; + border-right: 1px solid colors.$grey200; float: left; } @@ -41,13 +42,13 @@ div.segment-notes ul.graysmall li span.note-label { background-position: 50%; overflow-y: auto; cursor: pointer; - box-shadow: 0 0 0 #e0e0e0, 0 0 2px rgba(0, 0, 0, 0.12), + box-shadow: 0 0 0 colors.$grey200, 0 0 2px rgba(0, 0, 0, 0.12), 0 2px 4px rgba(0, 0, 0, 0.24); margin: 0 auto; } .segments-preview-container:hover { - box-shadow: 0 0 0 #e0e0e0, 0 0 8px rgba(0, 0, 0, 0.12), + box-shadow: 0 0 0 colors.$grey200, 0 0 8px rgba(0, 0, 0, 0.12), 0 2px 8px rgba(0, 0, 0, 0.24); transition: 0.2s ease; } @@ -61,7 +62,7 @@ div.segment-notes ul.graysmall li span.note-label { .segments-notes-container div.context-group { text-align: left; padding: 12px 20px; - color: #666; + color: colors.$grey700; list-style: none; font-size: 16px; word-break: break-word; @@ -108,16 +109,16 @@ div.segment-notes ul.graysmall li span.note-label { text-align: center; margin: 0 3px; border-radius: 2px; - border: 1px solid #c6c6c6; + border: 1px solid colors.$grey200; cursor: pointer; - color: #666666; + color: colors.$grey700; outline: none; position: relative; background-color: transparent; } .tab-preview-screenshot button:hover { - color: #000000; + color: colors.$black; } .tab-preview-screenshot button i { diff --git a/public/css/sass/components/segment/Tag.scss b/public/css/sass/components/segment/Tag.scss index ac594d44b1..9747d6697d 100644 --- a/public/css/sass/components/segment/Tag.scss +++ b/public/css/sass/components/segment/Tag.scss @@ -1,3 +1,5 @@ +@use '../../commons/colors'; +@use '../../commons/variables'; .DraftEditor-root { .public-DraftEditor-content > div > div { // everything @@ -9,7 +11,7 @@ content: '\21B5'; //↵ padding: 0 4px; font-size: 14px; - color: #08beec; + color: colors.$blue200; } } } @@ -52,10 +54,10 @@ display: flex; flex-direction: row; padding: 0 2px; - background: #002b5c; + background: colors.$blue900; font-size: 13px; line-height: 1.3; - color: #fff; + color: colors.$white; vertical-align: middle; word-break: break-all; //max-width: 11px; @@ -82,7 +84,7 @@ span { &::selection { - color: #fff; + color: colors.$white; background: transparent; } } @@ -96,7 +98,7 @@ bottom: 0; width: 0; height: 0; - border-left: 8px solid #002b5c; + border-left: 8px solid colors.$blue900; border-top: 8px solid transparent; border-bottom: 8px solid transparent; } @@ -111,7 +113,7 @@ top: 0; width: 0; height: 0; - border-right: 8px solid #002b5c; + border-right: 8px solid colors.$blue900; border-top: 8px solid transparent; border-bottom: 8px solid transparent; } @@ -126,7 +128,7 @@ top: 0; width: 0; height: 0; - border-right: 8px solid #002b5c; + border-right: 8px solid colors.$blue900; border-top: 8px solid transparent; border-bottom: 8px solid transparent; } @@ -137,15 +139,15 @@ bottom: 0; width: 0; height: 0; - border-left: 8px solid #002b5c; + border-left: 8px solid colors.$blue900; border-top: 8px solid transparent; border-bottom: 8px solid transparent; } } &.tag-ph { - border-radius: 8px; - background: #788190; + border-radius: variables.$border-radius-default; + background: colors.$grey500; margin: 0 1px; padding: 0 4px; max-width: unset; @@ -223,36 +225,36 @@ /* Tag states */ &.tag-inactive { - color: #788190; - background: #f5f6f7; + color: colors.$grey500; + background: colors.$grey50; &:before { - border-left-color: #f5f6f7; + border-left-color: colors.$grey50; } &:after { - border-right-color: #f5f6f7; + border-right-color: colors.$grey50; } } &.tag-clicked { - background-color: #2fb177; + background-color: colors.$green800; opacity: 1; &:before { - border-left-color: #2fb177; + border-left-color: colors.$green800; } &:after { - border-right-color: #2fb177; + border-right-color: colors.$green800; } } &.tag-focused { cursor: grab; opacity: 1; - background-color: #0099cc; + background-color: colors.$blue500; &:before { - border-left-color: #0099cc; + border-left-color: colors.$blue500; } &:after { - border-right-color: #0099cc; + border-right-color: colors.$blue500; } &:active { cursor: grabbing; @@ -262,35 +264,35 @@ &.tag-selected { cursor: grab; opacity: 1; - background-color: #0099cc; - box-shadow: 2px 0px 5px 2px #02c0ffa3; + background-color: colors.$blue500; + box-shadow: 2px 0px 5px 2px colors.$blue500; &:before { - border-left-color: #0099cc; + border-left-color: colors.$blue500; } &:after { - border-right-color: #0099cc; + border-right-color: colors.$blue500; } &:active { cursor: grabbing; } } &.tag-mismatch-error { - background-color: #e02020; + background-color: colors.$red500; &:before { - border-left-color: #e02020; + border-left-color: colors.$red500; } &:after { - border-right-color: #e02020; + border-right-color: colors.$red500; } } &.tag-mismatch-warning { - background-color: #ffcc01; + background-color: colors.$orange200; &:before { - border-left-color: #ffcc01; + border-left-color: colors.$orange200; } &:after { - border-right-color: #ffcc01; + border-right-color: colors.$orange200; } } @@ -302,7 +304,7 @@ &.tag-nbsp { font-size: 18px; margin: 0 2px; - color: #08beec; + color: colors.$blue200; background: transparent; &:before { border: none; @@ -312,7 +314,7 @@ } span { &::selection { - color: #002b5c; + color: colors.$blue900; } } } @@ -320,7 +322,7 @@ &.tag-word-joiner { font-size: 16px; margin: 0; - background: #08beec; + background: colors.$blue200; &:before { border: none; } @@ -329,7 +331,7 @@ } span { &::selection { - color: #002b5c; + color: colors.$blue900; } } } @@ -338,7 +340,7 @@ font-size: 17px; font-weight: 900; margin: 0; - color: #08beec; + color: colors.$blue200; background-color: transparent; &:before { border: none; @@ -348,7 +350,7 @@ } span { &::selection { - color: #002b5c; + color: colors.$blue900; } } } @@ -367,7 +369,7 @@ top: -7px; padding: 0 4px; font-size: 14px; - color: #08beec; + color: colors.$blue200; border: none; } } @@ -381,7 +383,7 @@ top: -7px; padding: 0 4px; font-size: 14px; - color: #08beec; + color: colors.$blue200; border: none; } } @@ -389,7 +391,7 @@ &.tag-tab { font-size: 14px; margin: 0 2px; - color: #08beec; + color: colors.$blue200; background: transparent; &:before { border: none; @@ -399,7 +401,7 @@ } span { &::selection { - color: #002b5c; + color: colors.$blue900; } } } @@ -408,7 +410,7 @@ font-size: 14px; font-family: 'icomoon'; margin: 0 2px; - color: #08beec; + color: colors.$blue200; background: transparent; &:before { border: none; @@ -418,7 +420,7 @@ } span { &::selection { - color: #002b5c; + color: colors.$blue900; } } &:hover { @@ -435,11 +437,11 @@ .index-counter { margin-left: 2px; margin-right: -3px; - background-color: #444c54; + background-color: colors.$grey700; border-radius: 10px; padding-left: 5px; padding-right: 5px; - box-shadow: inset 0px 0px 0px 1px #788190; + box-shadow: inset 0px 0px 0px 1px colors.$grey500; } } @@ -447,7 +449,7 @@ position: absolute; width: 140px; height: 32px; - background-color: #ccc; + background-color: colors.$grey200; top: -35px; border-radius: 2px; display: flex; @@ -466,7 +468,7 @@ left: 50%; transform: translateX(-50%); width: max-content; //240px; - background-color: #fff; + background-color: colors.$white; border-radius: 4px; display: -webkit-box; display: -webkit-flex; @@ -501,7 +503,7 @@ width: 14px; height: 14px; transform: rotate(45deg) translateX(-50%); - background: #ffffff; + background: colors.$white; } .tooltip-error-wrapper { @@ -552,14 +554,14 @@ } } .tooltip-error-ignore { - color: #757575; + color: colors.$grey600; text-decoration: none; cursor: pointer; border-radius: 0 4px 4px 0; padding-left: 10px; height: 40px; &:hover { - color: #525252; + color: colors.$grey700; } .icon-cancel-circle:before { line-height: 40px; @@ -616,8 +618,8 @@ padding: 1rem 0; font-weight: 700; line-height: 17px; - border-bottom: 1px solid #e0e3e8; - background: #fff; + border-bottom: 1px solid colors.$grey150; + background: colors.$white; align-items: center; cursor: default; .tag { @@ -636,7 +638,7 @@ } .tag-menu-suggestion { - border-bottom: 1px solid #e0e3e8; + border-bottom: 1px solid colors.$grey150; padding: 4px 0; color: rgb(0, 85, 184); text-overflow: ellipsis; @@ -647,7 +649,7 @@ cursor: pointer; &:hover, &.active { - background-color: #f2f5f7; + background-color: colors.$grey50; font-weight: 700; .tag-placeholder { transition: opacity 0.25s; @@ -680,8 +682,8 @@ } .place-here-tips { - border: 1px solid #08beec; - color: #08beec; + border: 1px solid colors.$blue200; + color: colors.$blue200; border-radius: 2px; padding: 1px 2px; line-height: 1.1; diff --git a/public/css/sass/components/segment/TooltipInfo.scss b/public/css/sass/components/segment/TooltipInfo.scss index dff65da8f8..102f6d371e 100644 --- a/public/css/sass/components/segment/TooltipInfo.scss +++ b/public/css/sass/components/segment/TooltipInfo.scss @@ -1,8 +1,9 @@ +@use '../../commons/colors'; .tooltip { position: absolute; width: 140px; height: 32px; - background-color: #ccc !important; + background-color: colors.$grey200 !important; top: -35px; border-radius: 2px; display: flex; diff --git a/public/css/sass/components/segment/issuesContainer.scss b/public/css/sass/components/segment/issuesContainer.scss index d99e6163a3..38396856b9 100644 --- a/public/css/sass/components/segment/issuesContainer.scss +++ b/public/css/sass/components/segment/issuesContainer.scss @@ -14,12 +14,12 @@ section.readonly .issues-container { display: inline-block !important; width: 100%; main-bottom: 0px; - border-bottom: 1px solid #ffffff; + border-bottom: 1px solid colors.$white; position: relative; z-index: 3; top: 0px; - border-top: 1px solid #ccc; - background: #ffffff !important; + border-top: 1px solid colors.$grey200; + background: colors.$white !important; .border-box-issue { width: 50%; display: inline-block; @@ -32,10 +32,10 @@ section.readonly .issues-container { display: inline-block; width: 50%; .ui.dropdown { - border: 1px solid #888; + border: 1px solid colors.$grey400; border-radius: 2px !important; &:hover { - border: 1px solid #96c8da; + border: 1px solid colors.$grey300; } .text { background: none; @@ -72,7 +72,7 @@ section.readonly .issues-container { border-top: 0 !important; border-radius: 0 0 2px 2px; &.visible { - border: 1px solid #96c8da; + border: 1px solid colors.$grey300; box-shadow: 0px 2px 3px 0px rgba(34, 36, 38, 0.15); } .item { @@ -104,9 +104,9 @@ section.readonly .issues-container { vertical-align: top; transition: 0.3s ease; .issue { - background: #ffffff; + background: colors.$white; padding: 5px 5px 5px 10px; - box-shadow: 0 0 0 #e0e0e0, 0 0 2px rgba(0, 0, 0, 0.12), + box-shadow: 0 0 0 colors.$grey200, 0 0 2px rgba(0, 0, 0, 0.12), 0 2px 4px rgba(0, 0, 0, 0.24) !important; .issue-head, .issue-activity-icon { @@ -146,26 +146,20 @@ section.readonly .issues-container { text-align: center; margin-right: 5px; background: transparent; - box-shadow: 0 0 0 1px #bcbcbc inset; + box-shadow: 0 0 0 1px colors.$grey300 inset; border: none; outline: none; - &.re-active { - background: #e9e9e9; - i { - color: #333333; - } - } &:hover { box-shadow: 0 0 0 1px rgba(34, 36, 38, 0.35) inset; i { - color: #333333; + color: colors.$grey1300; } } &:active { - background: #e3e3e3; + background: colors.$grey100; } &:focus { - box-shadow: 0 0 0 1px #96c8da inset; + box-shadow: 0 0 0 1px colors.$grey300 inset; } &:last-child { margin-right: 0; @@ -176,16 +170,6 @@ section.readonly .issues-container { position: relative; top: 1px; } - &.re-message { - i { - color: colors.$approvedGreen; - } - &:hover { - i { - color: #65a060; - } - } - } } } } @@ -194,9 +178,9 @@ section.readonly .issues-container { .re-comment-list { padding: 5px 10px; font-size: 18px; - background: #f0f2f5; - color: #787878; - box-shadow: 0 0 0 #e0e0e0, 0 0 2px rgba(0, 0, 0, 0.12), + background: colors.$grey75; + color: colors.$grey600; + box-shadow: 0 0 0 colors.$grey200, 0 0 2px rgba(0, 0, 0, 0.12), 0 2px 4px rgba(0, 0, 0, 0.24) !important; } .re-add-comment { @@ -208,20 +192,20 @@ section.readonly .issues-container { } .re-comment-list { font-size: 14px; - background: #ffffff; + background: colors.$white; .re-comment { margin-bottom: 0; .re-revisor { - color: colors.$approvedGreen; + color: colors.$green800; } .re-revisor2 { - color: colors.$approved2Green; + color: colors.$purple500; } .re-translator { - color: colors.$translatedBlue; + color: colors.$blue500; } .re-selected-text { - color: #000; + color: colors.$black; } .re-comment-date { font-size: 13px; @@ -243,8 +227,8 @@ section.readonly .issues-container { &.add-issue-segment { .category, .category-selected .severity { - border: 1px solid colors.$approvedGreen !important; - box-shadow: inset 0 0 3px colors.$approvedGreen; + border: 1px solid colors.$green800 !important; + box-shadow: inset 0 0 3px colors.$green800; } } } diff --git a/public/css/sass/components/segment/segment.scss b/public/css/sass/components/segment/segment.scss index 23e2eeabc4..6621a53cbd 100644 --- a/public/css/sass/components/segment/segment.scss +++ b/public/css/sass/components/segment/segment.scss @@ -2,13 +2,13 @@ @use '../../commons/variables'; .segment-selected-inBulk:not(.opened) { .body > .text { - background-color: #edf4fd !important; + background-color: colors.$blue50 !important; } .segment-add-inBulk { display: block; } &:hover .body > .text { - background-color: #edf4fd !important; + background-color: colors.$blue50 !important; } } @@ -24,12 +24,12 @@ display: none; } &:not(.editor):not(.muted):hover { - background: colors.$grey4; - color: #000; + background: colors.$grey100; + color: colors.$black; } &.segment-selected { - background: #c8cbd5 !important; - border: 1px solid #989898; + background: colors.$grey200 !important; + border: 1px solid colors.$grey400; } } @@ -40,14 +40,14 @@ body.cattool { display: none; } &.segment-selected-inBulk :hover { - background: #edf4fd !important; + background: colors.$blue50 !important; } } .editor.segment-selected-inBulk { - background: #edf4fd; + background: colors.$blue50; &:hover { - background: #edf4fd !important; + background: colors.$blue50 !important; } } } @@ -57,15 +57,15 @@ section { .header { height: 24px; width: 100%; - color: colors.$grey1; + color: colors.$grey500; font-size: 12px; - background: colors.$grey4 !important; + background: colors.$grey100 !important; margin-bottom: 0px; .percentuage { position: relative; display: none; width: 45px; - color: #fff; + color: colors.$white; font-size: 12px; text-decoration: none; font-weight: 100; @@ -87,9 +87,9 @@ section { .repetition { margin: 0 auto; text-transform: uppercase; - color: #fff; + color: colors.$white; font-size: 12px; - background: colors.$grey2; + background: colors.$grey300; padding: 4px 8px; position: relative; z-index: 12; @@ -117,7 +117,7 @@ section { } } } - &.opened { + &.opened .target{ .buttons { display: flex; align-items: center; @@ -125,6 +125,11 @@ section { text-align: right; z-index: 0; position: relative; + gap: 16px; + justify-content: flex-end; + button { + text-transform: uppercase; + } } .segment-body-content { .warnings-block { @@ -153,27 +158,27 @@ section { display: inline-block; width: 48%; margin: 0 1%; - color: #6a6a69; + color: colors.$grey700; min-height: 41px; &.error-alert { - background: #fdeae2; + background: colors.$grey75; .icon-column { - background-color: colors.$redDefaultTransparent; - color: colors.$redDefault; + background-color: colors.$red100; + color: colors.$red500; } } &.warning-alert { - background: #fff4e3; + background: colors.$grey75; .icon-column { - background-color: colors.$orangeDefaultTransparent; - color: colors.$orangeDefault; + background-color: colors.$orange100; + color: colors.$orange200; } } &.info-alert { - background: colors.$grey3; + background: colors.$grey150; .icon-column { - background-color: colors.$grey2; - color: colors.$grey1; + background-color: colors.$grey300; + color: colors.$grey500; } } .icon { @@ -233,7 +238,7 @@ section { flex-direction: column; } .collection-type-separator { - color: #777; + color: colors.$grey600; font-size: 16px; float: left; width: 100%; diff --git a/public/css/sass/components/segment/segmentFooter.scss b/public/css/sass/components/segment/segmentFooter.scss index 957f22247f..28753399f9 100644 --- a/public/css/sass/components/segment/segmentFooter.scss +++ b/public/css/sass/components/segment/segmentFooter.scss @@ -6,7 +6,7 @@ .submenu { .icon-warning2 { - color: #ea862c; + color: colors.$orange600; position: absolute; top: 8px; right: 10px; @@ -33,11 +33,11 @@ input { display: inline-block; width: 100%; - border: 1px solid #aaa; + border: 1px solid colors.$grey400; padding: 2px 0.4%; border-radius: 2px; - box-shadow: inset 0 1px 2px #ddd; - -webkit-box-shadow: inset 0 1px 2px #ddd; + box-shadow: inset 0 1px 2px colors.$grey200; + -webkit-box-shadow: inset 0 1px 2px colors.$grey200; text-align: left; min-height: 20px; } @@ -65,7 +65,7 @@ margin: 0; .ai-feature-grey-label { - color: colors.$grey7; + color: colors.$grey400; } } @@ -86,7 +86,7 @@ justify-content: space-between; gap: 16px; padding: 8px 12px 8px 16px; - border: 1px solid colors.$grey3; + border: 1px solid colors.$grey150; border-radius: 6px; > div { @@ -118,12 +118,12 @@ .ai-feature-option-alternative-description { font-size: 12px; - color: colors.$grey7; + color: colors.$grey400; } .ai-feature-alternatives-for { p { - color: colors.$grey6; + color: colors.$grey700; } } diff --git a/public/css/sass/components/segment/segmentFooterTabAiAssistant.scss b/public/css/sass/components/segment/segmentFooterTabAiAssistant.scss index 485d9bade8..4e50e26f8f 100644 --- a/public/css/sass/components/segment/segmentFooterTabAiAssistant.scss +++ b/public/css/sass/components/segment/segmentFooterTabAiAssistant.scss @@ -27,7 +27,7 @@ .feedback-container { display: flex; gap: 20px; - color: colors.$grey6; + color: colors.$grey700; } .feedback-container-submited { @@ -53,35 +53,35 @@ align-content: center; justify-content: center; align-items: center; - border: solid 1px colors.$grey8; + border: solid 1px colors.$grey200; border-radius: 4px; cursor: pointer; } .like { - color: colors.$approvedGreen; + color: colors.$green800; margin-right: 8px; &:hover, &.active { - border-color: colors.$approvedGreen; - background-color: rgba(colors.$approvedGreen, 0.1); + border-color: colors.$green800; + background-color: rgba(colors.$green800, 0.1); } } .dislike { - color: colors.$redDefault; + color: colors.$red500; &:hover, &.active { - border-color: colors.$redDefault; - background-color: rgba(colors.$redDefault, 0.1); + border-color: colors.$red500; + background-color: rgba(colors.$red500, 0.1); } } .submited { border: none; - background-color: rgba(colors.$grey1, 0.1); + background-color: rgba(colors.$grey500, 0.1); cursor: unset; } @@ -106,7 +106,7 @@ display: flex; flex-direction: column; - border-top: solid 1px colors.$grey3; + border-top: solid 1px colors.$grey150; } .tm-matches-title { diff --git a/public/css/sass/components/segment/segmentFooterTabGlossary.scss b/public/css/sass/components/segment/segmentFooterTabGlossary.scss index 8667fad6d5..2df6d807dc 100644 --- a/public/css/sass/components/segment/segmentFooterTabGlossary.scss +++ b/public/css/sass/components/segment/segmentFooterTabGlossary.scss @@ -1,7 +1,13 @@ @use '../../commons/colors'; +@use '../../commons/variables'; .tab.glossary { outline: none; + input, + textarea { + border-radius: variables.$border-radius-default; + } + .glossary-select, .input-with-label__wrapper { position: relative; @@ -13,18 +19,17 @@ margin-bottom: 4px; font-size: 14px; line-height: 16px; - color: colors.$grey6; + color: colors.$grey700; } } .glossary-select { .select-with-icon__wrapper { z-index: 2; svg { - color: colors.$grey2; + color: colors.$grey300; } } .select { - border-radius: 4px; line-height: 16px; } .select__dropdown-wrapper .custom-dropdown { @@ -50,7 +55,7 @@ width: 100%; input[type='checkbox'] { - accent-color: colors.$translatedBlue; + accent-color: colors.$blue500; } label { white-space: nowrap; @@ -68,16 +73,16 @@ } .dropdown__option--is-no-results-found { background-color: unset; - color: colors.$grey7; + color: colors.$grey400; } .dropdown__option--is-highlighted-option, .dropdown__option:hover { - background-color: colors.$grey8; + background-color: colors.$grey200; } .button-create-glossary-key { width: 100%; text-align: left; - color: colors.$grey6; + color: colors.$grey700; font-style: italic; font-size: 14px; border: none; @@ -86,7 +91,7 @@ padding: 0; &:hover { - color: colors.$grey6; + color: colors.$grey700; } } } @@ -99,18 +104,18 @@ .select__dropdown-wrapper .custom-dropdown { .dropdown__list { .dropdown__option--is-active-option { - background-color: colors.$grey4; - color: colors.$grey6; + background-color: colors.$grey100; + color: colors.$grey700; } .dropdown__option--is-no-results-found { display: none; } .dropdown__option--is-highlighted-option, .dropdown__option:hover { - background-color: colors.$grey8; + background-color: colors.$grey200; } .domain-option { - border: 1px solid colors.$grey7; + border: 1px solid colors.$grey400; border-radius: 12px; padding: 0 6px 0 6px; white-space: nowrap; @@ -120,7 +125,7 @@ text-align: center; } .button-create-option { - color: colors.$grey7; + color: colors.$grey400; font-style: italic; font-size: 12px; border: none; @@ -128,7 +133,7 @@ cursor: pointer; &:hover { - color: colors.$grey6; + color: colors.$grey700; } } } @@ -136,15 +141,14 @@ } input:not([type='radio']), textarea { - border: 1px solid colors.$grey2; - border-radius: 4px; + border: 1px solid colors.$grey300; padding: 4px 8px; outline: none; font-size: 14px; line-height: 16px; &:focus, &:focus-visible { - border-color: colors.$linkBlueTransparent; + border-color: colors.$blue300; } &.input-large { height: 64px; @@ -160,7 +164,7 @@ flex-direction: row; flex-wrap: nowrap; padding: 24px 32px; - border-bottom: 1px solid colors.$grey3; + border-bottom: 1px solid colors.$grey150; justify-content: space-between; } @@ -168,12 +172,12 @@ display: flex; flex-direction: row; align-items: center; - border: 1px solid #aebdcd; - border-radius: 4px; + border: 1px solid colors.$grey300; + border-radius: variables.$border-radius-default; padding: 4px; svg { - color: colors.$grey2; + color: colors.$grey300; } } @@ -201,7 +205,7 @@ .glossary__button-add { display: flex; flex-direction: row; - color: #fff; + color: colors.$white; font-weight: bold; text-decoration: none; margin-left: 4px; @@ -209,19 +213,19 @@ border-radius: 2px; font-size: 16px; line-height: 20px; - background: colors.$translatedBlue; - background: -moz-linear-gradient(top, colors.$translatedBlue, #119ec4); - background: linear-gradient(top, colors.$translatedBlue, #119ec4); + background: colors.$blue500; + background: -moz-linear-gradient(top, colors.$blue500, colors.$blue500); + background: linear-gradient(top, colors.$blue500, colors.$blue500); user-select: none; border: none; white-space: nowrap; cursor: pointer; &:hover { - background-color: colors.$translatedBlueHover; + background-color: colors.$blue600; } } .glossary__button-cancel { - color: colors.$translatedBlue; + color: colors.$blue500; font-weight: bold; text-decoration: none; padding: 6px 12px; @@ -234,7 +238,7 @@ white-space: nowrap; cursor: pointer; &:hover { - color: colors.$translatedBlueHover; + color: colors.$blue600; } } .glossary_items { @@ -243,11 +247,15 @@ overflow: auto; .glossary_item { padding: 24px 32px; - color: colors.$grey6; - font: 14px/16px calibri, Arial, Helvetica, sans-serif; + color: colors.$grey700; + font: + 14px/16px calibri, + Arial, + Helvetica, + sans-serif; text-align: left; &:nth-child(even) { - background: colors.$grey5; + background: colors.$grey50; } .glossary_item-header { display: flex; @@ -256,10 +264,10 @@ display: flex; flex-shrink: 0; > span { - color: colors.$grey6; + color: colors.$grey700; font-size: 12px; line-height: 15px; - border: 1px solid colors.$grey6; + border: 1px solid colors.$grey700; border-radius: 12px; padding: 0 4px; overflow: hidden; @@ -307,7 +315,7 @@ flex-shrink: 0; > span { - color: colors.$grey7; + color: colors.$grey400; font-size: 10px; margin-left: 8px; } @@ -325,7 +333,7 @@ text-overflow: ellipsis; span { - color: colors.$grey7; + color: colors.$grey400; } } .glossary_item-actions { @@ -334,9 +342,9 @@ align-items: center; gap: 12px; padding-left: 16px; - color: colors.$grey7; + color: colors.$grey400; svg:hover { - color: colors.$grey6; + color: colors.$grey700; } > * { @@ -385,7 +393,7 @@ align-items: center; svg { cursor: pointer; - color: colors.$grey7; + color: colors.$grey400; } } @@ -399,10 +407,10 @@ } .forbidden-badge { - background-color: colors.$grey4; + background-color: colors.$grey100; font-weight: normal; font-size: 14px; - color: colors.$grey6; + color: colors.$grey700; border-radius: 4px; padding: 2px 6px; margin-left: 10px; @@ -502,10 +510,11 @@ display: flex; gap: 0; justify-content: space-between; - color: colors.$grey2; + color: colors.$grey300; > div { width: auto; display: flex; + gap: 8px; flex-direction: row; } > div:first-child { @@ -542,11 +551,11 @@ } .select--is-disabled { - background-color: colors.$grey4; + background-color: colors.$grey100; } .segmented-control { - background-color: colors.$grey3; + background-color: colors.$grey150; .segmented-control__cursor { padding: unset; height: 74%; diff --git a/public/css/sass/components/segment/segmentFooterTabIcu.scss b/public/css/sass/components/segment/segmentFooterTabIcu.scss index 1d2e98b65d..9f403be10c 100644 --- a/public/css/sass/components/segment/segmentFooterTabIcu.scss +++ b/public/css/sass/components/segment/segmentFooterTabIcu.scss @@ -1,4 +1,5 @@ -@use "../../commons/colors"; +@use '../../commons/colors'; +@use '../../commons/variables'; .segment-footer-icu-container.open { h3 { margin: 0; @@ -11,7 +12,8 @@ padding: 24px; gap: 60px; } - .segment-footer-icu-plurals, .segment-footer-icu-editor { + .segment-footer-icu-plurals, + .segment-footer-icu-editor { width: 50%; } .segment-footer-icu-plurals { @@ -45,8 +47,8 @@ font-weight: 700; font-size: 14px; } - .rule { - color: colors.$grey7; + .rule { + color: colors.$grey400; font-size: 14px; width: 100%; max-width: 120px; @@ -74,8 +76,8 @@ grid-column: 1 / span 1; justify-self: stretch; border-radius: 16px; - border: 1px solid colors.$grey3; - background: colors.$grey5; + border: 1px solid colors.$grey150; + background: colors.$grey50; width: 184px; height: 50px; justify-content: space-between; @@ -94,9 +96,9 @@ div { text-transform: capitalize; span { - color: colors.$grey7; - font-weight: 400; - margin-left: 4px; + color: colors.$grey400; + font-weight: 400; + margin-left: 4px; } } } @@ -123,8 +125,8 @@ justify-content: flex-start; gap: 8px; align-self: stretch; - border-radius: 8px; - background: colors.$grey5; + border-radius: variables.$border-radius-default; + background: colors.$grey50; align-content: flex-start; text-align: left; &.rtl { @@ -132,4 +134,4 @@ } } } -} \ No newline at end of file +} diff --git a/public/css/sass/components/segment/tagsMenu.scss b/public/css/sass/components/segment/tagsMenu.scss index f1af5b60a0..9166d25cea 100644 --- a/public/css/sass/components/segment/tagsMenu.scss +++ b/public/css/sass/components/segment/tagsMenu.scss @@ -1,11 +1,12 @@ +@use '../../commons/colors'; .target { .tags-auto-complete-menu { - background: #fff; + background: colors.$white; box-sizing: border-box; max-width: 300px; border-radius: 2px; box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.3); - border: 1px solid #dadada; + border: 1px solid colors.$grey200; .ui.vertical.menu { -webkit-box-shadow: none; -moz-box-shadow: none; @@ -21,10 +22,10 @@ padding: 1rem 1.14rem; font-weight: bold; line-height: 17px; - border-top: 1px solid #e9e3e8; - border-bottom: 1px solid #e0e3e8; + border-top: 1px solid colors.$grey100; + border-bottom: 1px solid colors.$grey150; z-index: 1; - background: #fff; + background: colors.$white; pointer-events: none; display: flex; align-items: center; @@ -32,7 +33,7 @@ padding: 4px 7px; margin: 0 5px; &.mismatch { - color: #e1565a; + color: colors.$red400; } } } @@ -46,27 +47,27 @@ cursor: pointer; &:before { - background: #fff; + background: colors.$white; } &:hover { background: rgba(0, 0, 0, 0.05) !important; } &.added-tag { - color: #767676 !important; + color: colors.$grey600 !important; & a { - color: #767676 !important; + color: colors.$grey600 !important; } } &.missing-tag { - color: #000 !important; + color: colors.$black !important; font-size: 16px; & a { - color: #000 !important; + color: colors.$black !important; } } mark { - background: #ffff00; + background: colors.$orange200; } &.no-results { cursor: default; @@ -78,9 +79,9 @@ } } .head-tag-list .locked.mismatch { - background-color: #fdeae2; - color: #e1595d; - box-shadow: inset 0 0px 0 2px #e1565a; + background-color: colors.$grey75; + color: colors.$red400; + box-shadow: inset 0 0px 0 2px colors.$red400; font-weight: 100; padding: 4px 6px; position: relative; @@ -90,11 +91,11 @@ .style-tag { display: inline-flex; - background: #f2f4f7; - box-shadow: inset 0 0 0 2px #e5e9f1; + background: colors.$grey50; + box-shadow: inset 0 0 0 2px colors.$grey100; border-radius: 7px; font-size: 15px; - color: #767676; + color: colors.$grey600; font-style: italic; padding: 0 6px 0 3px; vertical-align: middle; @@ -105,31 +106,31 @@ background: transparent !important; } &:hover { - background: #e5e9f1; + background: colors.$grey100; cursor: pointer; } a { - color: #3b4a5c; + color: colors.$grey1300; font-weight: 700; } &.mismatch { - background-color: #fdeae2; - box-shadow: inset 0 0 0 2px #f9dcd1; + background-color: colors.$grey75; + box-shadow: inset 0 0 0 2px colors.$red100; &:hover { - background-color: #f9dcd1; + background-color: colors.$red100; } &.selected { - box-shadow: inset 0 0 0 2px #e1565a; - background: #f9d7ca; + box-shadow: inset 0 0 0 2px colors.$red400; + background: colors.$red100; } &, a { - color: #e1565a; + color: colors.$red400; } } &.highlight { - box-shadow: inset 0 0 0 2px #3b4a5c96; - color: #424242; + box-shadow: inset 0 0 0 2px colors.$grey1300; + color: colors.$grey1300; } &.selected { cursor: grab; diff --git a/public/css/sass/components/settingsPanel/AnalysisTab.scss b/public/css/sass/components/settingsPanel/AnalysisTab.scss index 33a8710a40..6b581c42dd 100644 --- a/public/css/sass/components/settingsPanel/AnalysisTab.scss +++ b/public/css/sass/components/settingsPanel/AnalysisTab.scss @@ -1,4 +1,5 @@ @use '../../commons/colors'; +@use '../../commons/variables'; .analysis-tab { display: flex; @@ -11,7 +12,7 @@ .analysis-value-not-saved, .analysis-value-not-saved span, .analysis-value-not-saved input { - color: colors.$translatedBlue; + color: colors.$blue500; } &.settings-panel-contentwrapper-tab-background { @@ -22,7 +23,7 @@ span { display: block; text-align: left; - color: colors.$grey6; + color: colors.$grey700; } .analysis-tab-head { span { @@ -34,9 +35,9 @@ input.input-percentage { height: 40px; width: 76px; - border: 1px solid colors.$grey4; + border: 1px solid colors.$grey200; padding: 8px 12px 8px 12px; - box-shadow: 2px 2px 4px 0px #00000014 inset; + border-radius: variables.$border-radius-default; font-size: 16px; line-height: 24px; font-weight: 400; @@ -54,17 +55,17 @@ } .analysis-tab-tableContainer { table { - border: 1px solid colors.$grey3; + border: 1px solid colors.$grey150; border-spacing: 0; border-collapse: separate; - border-radius: 4px; + border-radius: variables.$border-radius-default; overflow: hidden; th:not(:last-child), td:not(:last-child) { - border-right: 1px solid colors.$grey3; + border-right: 1px solid colors.$grey150; } thead > tr > th { - border-bottom: 1px solid colors.$grey3; + border-bottom: 1px solid colors.$grey150; } th { height: 64px; @@ -86,9 +87,9 @@ } .analysis-tab-exceptionsContainer { background: colors.$white; - border: 1px solid colors.$grey3; + border: 1px solid colors.$grey150; padding: 24px; - border-radius: 4px; + border-radius: variables.$border-radius-default; display: flex; flex-direction: column; .analysis-tab-subhead .input-percentage { @@ -137,14 +138,13 @@ padding: 9px 46px 9px 12px; border-radius: 2px; border: 1px solid rgba(34, 36, 38, 0.15); - box-shadow: inset 0 1px 3px #ddd; } .dropdown__search-bar { height: 34px; margin: 0 12px 12px; border-radius: 4px; border: 1px solid rgba(34, 36, 38, 0.15); - background-color: #fff; + background-color: colors.$white; outline: none; .dropdown__search-bar-input { width: 100%; @@ -175,9 +175,6 @@ } .analysis-tab-buttons { gap: 8px; - button { - height: 32px; - } } button.add-button { width: 148px; diff --git a/public/css/sass/components/settingsPanel/EditorOtherTab.scss b/public/css/sass/components/settingsPanel/EditorOtherTab.scss index 76dbed07be..d365c8d6de 100644 --- a/public/css/sass/components/settingsPanel/EditorOtherTab.scss +++ b/public/css/sass/components/settingsPanel/EditorOtherTab.scss @@ -15,7 +15,7 @@ cursor: help; font-weight: bold; text-decoration: underline; - color: #000; + color: colors.$black; cursor: pointer; margin-left: 6px; } @@ -45,6 +45,6 @@ > p { font-weight: normal; - color: colors.$grey6; + color: colors.$grey700; } } diff --git a/public/css/sass/components/settingsPanel/EditorSettingsTab.scss b/public/css/sass/components/settingsPanel/EditorSettingsTab.scss index a348741d1f..6995590a0f 100644 --- a/public/css/sass/components/settingsPanel/EditorSettingsTab.scss +++ b/public/css/sass/components/settingsPanel/EditorSettingsTab.scss @@ -1,4 +1,5 @@ @use '../../commons/colors'; +@use '../../commons/variables'; .editor-settings-options-box { float: left; width: 100%; @@ -31,7 +32,7 @@ > p { font-size: 16px; - color: colors.$grey6; + color: colors.$grey700; } } @@ -54,23 +55,21 @@ .select { font-size: 16px; padding: 9px 46px 9px 12px; - border-radius: 2px; + border-radius: variables.$border-radius-default; border: 1px solid rgba(34, 36, 38, 0.15); - box-shadow: inset 0 1px 3px #ddd; &:hover { border-color: rgba(34, 36, 38, 0.35); - box-shadow: none; } } .select--is-focused, .select--is-focused:hover { - border: solid 1px #96c8da; + border: solid 1px colors.$grey300; } .select--is-disabled { - background-color: #f3f3f3; + background-color: colors.$grey75; } .custom-dropdown { @@ -112,7 +111,7 @@ } .dropdown__option--is-no-results-found { - color: colors.$grey7; + color: colors.$grey400; } .dropdown__option--is-no-results-found { @@ -122,12 +121,12 @@ .dropdown__option--is-active-option { background-color: unset; font-weight: bold; - background-color: colors.$grey5; + background-color: colors.$grey50; } .dropdown__option--is-highlighted-option, .dropdown__option:hover { - background-color: colors.$grey4; + background-color: colors.$grey100; } } @@ -138,7 +137,7 @@ input:not([type='radio']), textarea { - border: 1px solid colors.$grey2; + border: 1px solid colors.$grey300; border-radius: 4px; padding: 4px 8px; outline: none; @@ -146,7 +145,7 @@ line-height: 16px; &:focus, &:focus-visible { - border-color: colors.$linkBlueTransparent; + border-color: colors.$blue300; } } .dropdown__search-bar { diff --git a/public/css/sass/components/settingsPanel/FileImportTab.scss b/public/css/sass/components/settingsPanel/FileImportTab.scss index cb6fa70529..aaa63c696f 100644 --- a/public/css/sass/components/settingsPanel/FileImportTab.scss +++ b/public/css/sass/components/settingsPanel/FileImportTab.scss @@ -8,7 +8,7 @@ p { display: block; text-align: left; - color: colors.$grey6; + color: colors.$grey700; font-size: 16px; line-height: 24px; } @@ -24,7 +24,7 @@ top: 0; z-index: 4; width: 100%; - background-color: colors.$grey5; + background-color: colors.$grey50; &:has(.select__dropdown-wrapper) { z-index: 5; @@ -74,7 +74,7 @@ .custom-segmented-control { .segmented-control { - background-color: colors.$grey8; + background-color: colors.$grey200; } .segmented-control__label { line-height: 28px; @@ -107,7 +107,7 @@ } .unsaved { - color: colors.$translatedBlue; + color: colors.$blue500; } } @@ -119,7 +119,7 @@ .select { color: colors.$black; - border-color: colors.$grey8; + border-color: colors.$grey200; } .select-with-label__wrapper .select { @@ -127,7 +127,7 @@ } .select--is-disabled { - background-color: colors.$grey9; + background-color: colors.$grey75; } } @@ -173,23 +173,16 @@ .select { font-size: 16px; padding: 9px 46px 9px 12px; - border-radius: 2px; border: 1px solid rgba(34, 36, 38, 0.15); - box-shadow: inset 0 1px 3px #ddd; - - &:hover { - border-color: rgba(34, 36, 38, 0.35); - box-shadow: none; - } } .select--is-focused, .select--is-focused:hover { - border: solid 1px #96c8da; + border: solid 1px colors.$grey300; } .select--is-disabled { - background-color: #f3f3f3; + background-color: colors.$grey75; } .custom-dropdown { @@ -230,7 +223,7 @@ } .dropdown__option--is-no-results-found { - color: colors.$grey7; + color: colors.$grey400; } .dropdown__option--is-no-results-found { @@ -240,12 +233,12 @@ .dropdown__option--is-active-option { background-color: unset; font-weight: bold; - background-color: colors.$grey5; + background-color: colors.$grey50; } .dropdown__option--is-highlighted-option, .dropdown__option:hover { - background-color: colors.$grey4; + background-color: colors.$grey100; } } @@ -256,7 +249,7 @@ input:not([type='radio']), textarea { - border: 1px solid colors.$grey2; + border: 1px solid colors.$grey300; border-radius: 4px; padding: 4px 8px; outline: none; @@ -264,7 +257,7 @@ line-height: 16px; &:focus, &:focus-visible { - border-color: colors.$linkBlueTransparent; + border-color: colors.$blue300; } } .dropdown__search-bar { diff --git a/public/css/sass/components/settingsPanel/MachineTranslationTab.scss b/public/css/sass/components/settingsPanel/MachineTranslationTab.scss index 73f7b966ba..d99a3f4069 100644 --- a/public/css/sass/components/settingsPanel/MachineTranslationTab.scss +++ b/public/css/sass/components/settingsPanel/MachineTranslationTab.scss @@ -1,4 +1,5 @@ @use '../../commons/colors'; +@use '../../commons/variables'; .machine-translation-tab { .add-mt-button, .add-mt-container { @@ -102,18 +103,16 @@ border-radius: 2px; border: 1px solid rgba(34, 36, 38, 0.15); height: 37px; - box-shadow: inset 0 1px 3px #ddd; &:hover { border-color: rgba(34, 36, 38, 0.35); - box-shadow: none; } } .field-error { - color: colors.$redDefault; + color: colors.$red500; font-size: 12px; } .mt-error { - color: colors.$redDefault; + color: colors.$red500; } &.container-actions { @@ -127,11 +126,11 @@ width: 50%; text-align: left; padding: 16px; - background: colors.$grey4; + background: colors.$grey100; display: flex; flex-direction: column; - border: 1px solid colors.$grey3; - border-radius: 8px; + border: 1px solid colors.$grey150; + border-radius: variables.$border-radius-default; .button { margin-top: 20px; @@ -155,11 +154,11 @@ } .green-button { - background-color: #33b079 !important; + background-color: colors.$green800 !important; color: white !important; &:hover { - background-color: rgba($color: #33b079, $alpha: 0.9) !important; + background-color: rgba($color: colors.$green800, $alpha: 0.9) !important; } } } @@ -197,13 +196,10 @@ .select { font-size: 16px; padding: 9px 46px 9px 12px; - border-radius: 2px; border: 1px solid rgba(34, 36, 38, 0.15); - box-shadow: inset 0 1px 3px #ddd; color: black; &:hover { border-color: rgba(34, 36, 38, 0.35); - box-shadow: none; } } @@ -296,7 +292,7 @@ display: flex; align-items: center; justify-content: center; - background-color: #eaebee; + background-color: colors.$grey100; > button { background: unset; @@ -331,6 +327,10 @@ .settings-panel-row-content { grid-template-columns: 8% minmax(0, 1fr) 22% 5%; background-color: unset; + + > :first-child { + margin-top: 5px; + } } .settings-panel-row-content { grid-template-columns: 8% minmax(0, 1fr) 22% 5%; @@ -370,6 +370,10 @@ align-items: center; justify-content: space-between; } + + .glossary-row-name { + align-items: center; + } } .glossary-row-name { @@ -390,7 +394,7 @@ width: 100%; padding: 4px; background-color: unset; - border: 1px solid colors.$grey8; + border: 1px solid colors.$grey200; border-radius: 3px; text-overflow: ellipsis; white-space: nowrap; @@ -404,11 +408,14 @@ } &.error { - border: solid 1px colors.$redDefault; + border: solid 1px colors.$red500; } } .glossary-deepl-row-name-input { + padding: 4px 8px; + border-radius: variables.$border-radius-default; + &:hover { background-color: unset; } @@ -429,8 +436,12 @@ } .grey-button { + font-size: 14px !important; + border-radius: variables.$border-radius-default; + height: 32px; + &.error { - border: solid 1px colors.$redDefault; + border: solid 1px colors.$red500; } } @@ -468,15 +479,15 @@ gap: 8px; border-radius: 2px; font-size: 16px; - color: #000; - background: #eaebee; + color: colors.$black; + background: colors.$grey100; padding: 0 8px; text-align: center; - border: 1px solid #9e9e9e; + border: 1px solid colors.$grey400; cursor: pointer; &:hover { - background-color: colors.$grey5; + background-color: colors.$grey50; } &:disabled { @@ -509,6 +520,11 @@ .settings-panel-table-rows-container { max-height: 400px; overflow-y: auto; + border: unset; + } + + > :first-child { + margin-bottom: 10px; } } @@ -545,10 +561,10 @@ gap: 15px; align-items: center; justify-content: space-between; - background-color: colors.$grey4; + background-color: colors.$grey100; padding: 12px; - border-radius: 8px; - border: solid 1px colors.$grey3; + border-radius: variables.$border-radius-default; + border: solid 1px colors.$grey150; margin-bottom: 16px; h4 { @@ -582,7 +598,7 @@ } p { - color: colors.$grey6; + color: colors.$grey700; } } @@ -598,8 +614,8 @@ display: flex; align-items: center; justify-content: center; - background-color: #eaebee; - border-radius: 8px; + background-color: colors.$grey100; + border-radius: variables.$border-radius-default; > button { background: unset; @@ -623,16 +639,18 @@ &.options-container-expanded { .expand-button { - border-radius: 8px 8px 0 0; + border-radius: variables.$border-radius-default + variables.$border-radius-default 0 0; } } .options-container-content { display: flex; flex-direction: column; - border-radius: 0 0 8px 8px; + border-radius: 0 0 variables.$border-radius-default + variables.$border-radius-default; padding: 24px; - background-color: colors.$grey5; + background-color: colors.$grey50; .mt-params-option { display: flex; @@ -661,7 +679,7 @@ p { display: block; text-align: left; - color: colors.$grey6; + color: colors.$grey700; font-size: 16px; line-height: 24px; } @@ -674,7 +692,7 @@ .select { color: colors.$black; - border-color: colors.$grey8; + border-color: colors.$grey200; } .select-with-label__wrapper .select { @@ -683,7 +701,13 @@ } .select--is-disabled { - background-color: colors.$grey9; + background-color: colors.$grey75; + } + + input { + height: 32px; + padding: 4px 8px; + border-radius: variables.$border-radius-default; } } @@ -695,7 +719,7 @@ position: sticky; top: -1px; - background: colors.$grey5; + background: colors.$grey50; &::after { display: block; @@ -704,9 +728,9 @@ margin-top: 5px; background: linear-gradient( 90deg, - rgba(colors.$grey8, 0.6) 0%, - rgba(colors.$grey8, 0.6) 75%, - rgba(colors.$grey8, 0) 100% + rgba(colors.$grey200, 0.6) 0%, + rgba(colors.$grey200, 0.6) 75%, + rgba(colors.$grey200, 0) 100% ); } } @@ -716,7 +740,7 @@ } .dropdown__search-bar { - border-bottom: 1px #d7d8db solid; + border-bottom: 1px colors.$grey200 solid; margin-bottom: 1px; } diff --git a/public/css/sass/components/settingsPanel/MessageNotification.scss b/public/css/sass/components/settingsPanel/MessageNotification.scss index eb5c0b1273..a156e50c51 100644 --- a/public/css/sass/components/settingsPanel/MessageNotification.scss +++ b/public/css/sass/components/settingsPanel/MessageNotification.scss @@ -5,7 +5,7 @@ font-size: 15px; justify-content: space-between; padding: 15px 10px; - border: 1px solid colors.$grey8; + border: 1px solid colors.$grey200; margin: 15px 0; > div { display: flex; @@ -16,16 +16,16 @@ margin: 0; } &.settingsPanel-notification_success { - border-top: 3px solid colors.$greenDefault; - background-color: colors.$greenDefaultTransparent2; + border-top: 3px solid colors.$green500; + background-color: colors.$green50; } &.settingsPanel-notification_warning { - border-top: 3px solid #ffcc01; - background-color: colors.$orangeDefaultTransparent2; + border-top: 3px solid colors.$orange200; + background-color: colors.$orange50; } &.settingsPanel-notification_error { - border-top: 3px solid colors.$redDefault; - background-color: colors.$redDefaultTransparent; + border-top: 3px solid colors.$red500; + background-color: colors.$red100; } .button-close { padding: 2px 4px; diff --git a/public/css/sass/components/settingsPanel/OtherTab.scss b/public/css/sass/components/settingsPanel/OtherTab.scss index b3c6ae0865..b447e90c89 100644 --- a/public/css/sass/components/settingsPanel/OtherTab.scss +++ b/public/css/sass/components/settingsPanel/OtherTab.scss @@ -31,7 +31,7 @@ > p { font-size: 16px; - color: colors.$grey6; + color: colors.$grey700; } } @@ -54,23 +54,20 @@ .select { font-size: 16px; padding: 9px 46px 9px 12px; - border-radius: 2px; border: 1px solid rgba(34, 36, 38, 0.15); - box-shadow: inset 0 1px 3px #ddd; &:hover { border-color: rgba(34, 36, 38, 0.35); - box-shadow: none; } } .select--is-focused, .select--is-focused:hover { - border: solid 1px #96c8da; + border: solid 1px colors.$grey300; } .select--is-disabled { - background-color: #f3f3f3; + background-color: colors.$grey75; } .custom-dropdown { @@ -111,7 +108,7 @@ } .dropdown__option--is-no-results-found { - color: colors.$grey7; + color: colors.$grey400; } .dropdown__option--is-no-results-found { @@ -121,12 +118,12 @@ .dropdown__option--is-active-option { background-color: unset; font-weight: bold; - background-color: colors.$grey5; + background-color: colors.$grey50; } .dropdown__option--is-highlighted-option, .dropdown__option:hover { - background-color: colors.$grey4; + background-color: colors.$grey100; } } @@ -137,7 +134,7 @@ input:not([type='radio']), textarea { - border: 1px solid colors.$grey2; + border: 1px solid colors.$grey300; border-radius: 4px; padding: 4px 8px; outline: none; @@ -145,7 +142,7 @@ line-height: 16px; &:focus, &:focus-visible { - border-color: colors.$linkBlueTransparent; + border-color: colors.$blue300; } } .dropdown__search-bar { @@ -183,7 +180,7 @@ cursor: help; font-weight: bold; text-decoration: underline; - color: #000; + color: colors.$black; cursor: pointer; margin-left: 6px; } @@ -224,6 +221,6 @@ > p { font-weight: normal; - color: colors.$grey6; + color: colors.$grey700; } } diff --git a/public/css/sass/components/settingsPanel/QualityFrameworkTab.scss b/public/css/sass/components/settingsPanel/QualityFrameworkTab.scss index 83634218d3..2822b8e7ad 100644 --- a/public/css/sass/components/settingsPanel/QualityFrameworkTab.scss +++ b/public/css/sass/components/settingsPanel/QualityFrameworkTab.scss @@ -1,4 +1,5 @@ @use '../../commons/colors'; +@use '../../commons/variables'; .quality-framework-tab { &.settings-panel-contentwrapper-tab-background { @@ -8,7 +9,7 @@ p { display: block; text-align: left; - color: #666666; + color: colors.$grey700; font-size: 16px; line-height: 24px; } @@ -47,6 +48,8 @@ overflow-x: auto; overscroll-behavior: none; scrollbar-width: thin; + border-radius: variables.$border-radius-default; + border: 1px solid colors.$grey150; @media (max-height: 1200px) { max-height: calc(100vh - 470px); @@ -68,7 +71,7 @@ align-items: center; justify-content: center; min-height: 64px; - background-color: colors.$grey3; + background-color: colors.$grey150; font-weight: bold; z-index: 1; } @@ -77,10 +80,11 @@ display: flex; justify-content: space-between; max-width: 280px; - /* height: 64px; */ min-height: 64px; background-color: colors.$white; - border: 1px solid colors.$grey3; + border: 1px solid colors.$grey150; + border-bottom: unset; + border-left: unset; border-left-width: 2px; padding: 0 10px; @@ -124,7 +128,7 @@ .header { position: sticky; top: 0; - background-color: colors.$grey3; + background-color: colors.$grey150; z-index: 1; > :first-child { position: sticky; @@ -145,10 +149,10 @@ .column { display: grid; - grid-template-columns: 1fr 10%; + grid-template-columns: 1fr 20%; align-items: center; height: 32px; - border: 1px solid colors.$grey3; + border: 1px solid colors.$grey150; padding: 0 10px; .label { @@ -172,7 +176,9 @@ .cell { display: flex; justify-content: center; - border: 1px solid colors.$grey3; + border: 1px solid colors.$grey150; + border-right: unset; + border-bottom: unset; padding: 10px; height: 64px; @@ -182,7 +188,7 @@ } .cell-not-saved { input { - color: colors.$translatedBlue; + color: colors.$blue500; } } @@ -206,9 +212,9 @@ .quality-framework-input { height: 40px; width: 100%; - border: 1px solid colors.$grey4; + border: 1px solid colors.$grey200; padding: 8px 12px 8px 12px; - box-shadow: 2px 2px 4px 0px #00000014 inset; + border-radius: variables.$border-radius-default; font-size: 16px; line-height: 24px; font-weight: 400; @@ -216,8 +222,8 @@ } .quality-framework-input-error { - outline-color: colors.$redDefaultHover; - border-color: colors.$redDefaultHover; + outline-color: colors.$red600; + border-color: colors.$red600; border-radius: 4px; border-width: 2px; } @@ -241,7 +247,7 @@ } .quality-framework-error-message { - color: colors.$redDefaultHover; + color: colors.$red600; } .quality-framework-add-category { @@ -269,7 +275,7 @@ padding: 4px 5px; } .icon.active { - background-color: colors.$grey4; + background-color: colors.$grey100; border-radius: 3px; } } @@ -298,7 +304,7 @@ } .quality-framework-not-saved { - color: colors.$translatedBlue; + color: colors.$blue500; } .quality-framework-modify-category, @@ -331,9 +337,9 @@ justify-content: end; width: 100%; height: 40px; - border: 1px solid colors.$grey4; + border: 1px solid colors.$grey200; padding: 8px 4px 8px 0; - box-shadow: 2px 2px 4px 0px #00000014 inset; + border-radius: variables.$border-radius-default; input { position: absolute; @@ -350,11 +356,10 @@ button { width: 20px !important; height: 20px !important; - z-index: 2; - color: colors.$grey2 !important; + color: colors.$grey300 !important; &:hover { - color: colors.$grey1 !important; + color: colors.$grey500 !important; } } } @@ -363,11 +368,11 @@ align-items: center; button { - color: colors.$grey2 !important; + color: colors.$grey300 !important; gap: unset; &:hover { - color: colors.$grey1 !important; + color: colors.$grey500 !important; } } } diff --git a/public/css/sass/components/settingsPanel/SettingsPanel.scss b/public/css/sass/components/settingsPanel/SettingsPanel.scss index bb09f691a0..1f8a4f15fc 100644 --- a/public/css/sass/components/settingsPanel/SettingsPanel.scss +++ b/public/css/sass/components/settingsPanel/SettingsPanel.scss @@ -1,4 +1,5 @@ @use '../../commons/colors'; +@use '../../commons/variables'; .settings-panel { position: absolute; @@ -57,7 +58,7 @@ align-items: center; height: 55px; padding: 0 10px; - background-color: colors.$darkBlue; + background-color: colors.$blue900; color: white; > span { @@ -93,12 +94,12 @@ } .settings-panel-tab-active { - background-color: rgba(colors.$grey3, 0.24); + background-color: rgba(colors.$grey150, 0.24); opacity: 1; } .settings-panel-tab-modifyng-icon { - color: colors.$translatedBlue; + color: colors.$blue500; margin-right: 5px; } @@ -106,7 +107,7 @@ > ul { display: flex; gap: 1px; - background-color: colors.$darkBlue; + background-color: colors.$blue900; } } @@ -150,15 +151,12 @@ span { font-size: 16px; - color: colors.$grey6; + color: colors.$grey700; } } .settings-panel-button-icon { min-width: 120px; - display: flex !important; - gap: 10px !important; - margin: 0 !important; } .settings-panel-templates { @@ -166,7 +164,7 @@ align-items: end; padding: 16px 24px; - background-color: colors.$darkBlue; + background-color: colors.$blue900; .select-with-label__wrapper { width: 240px; @@ -192,13 +190,13 @@ .dropdown__option--is-active-option { color: colors.$white; - background-color: colors.$darkBlue; + background-color: colors.$blue900; } } .select { color: colors.$black; - border-color: colors.$grey8; + border-color: colors.$grey200; } } @@ -220,9 +218,10 @@ height: 38px; font-size: 16px; padding: 9px 0 9px 12px; + border-radius: variables.$border-radius-default; border: none; position: absolute; - margin-top: 37px; + margin-top: 51px; margin-left: 1px; outline: none; line-height: 4; @@ -238,11 +237,10 @@ border-radius: unset; font-weight: normal; color: black !important; - box-shadow: inset 0 0 0 1px colors.$grey8; + box-shadow: inset 0 0 0 1px colors.$grey200; } button.template-button-white { - border-radius: unset; font-weight: normal; color: white !important; box-shadow: inset 0 0 0 1px colors.$white; @@ -265,10 +263,10 @@ } .button-more-items { - border-radius: unset; + border-radius: variables.$border-radius-default; font-weight: normal; color: black; - box-shadow: inset 0 0 0 1px colors.$grey8; + box-shadow: inset 0 0 0 1px colors.$grey200; padding: 0; &:hover { @@ -284,6 +282,20 @@ width: 40px; height: 40px; } + + .menu-button-wrapper { + > button { + svg { + color: white; + } + + &:hover, + &:focus { + background-color: unset; + color: unset; + } + } + } } .button-more-items-project-templates { @@ -296,18 +308,18 @@ } button.button-save-changes { - background-color: colors.$grey4; + background-color: colors.$grey100; color: black !important; &:hover { - background-color: colors.$grey4 !important; + background-color: colors.$grey100 !important; opacity: 0.8; } } } .settings-panel-contentwrapper-tab-background { - background-color: colors.$grey5; + background-color: colors.$grey50; padding: 20px; border-radius: 16px; } @@ -318,7 +330,7 @@ display: inline-block; width: 100%; content: ''; - border-top: solid 2px rgba(colors.$darkBlueTransparent, 0.5); + border-top: solid 2px rgba(colors.$blue50, 0.5); } > h2 { @@ -354,7 +366,7 @@ font-weight: bold; div { - color: colors.$linkBlue; + color: colors.$blue700; } } @@ -416,7 +428,7 @@ .settings-panel-subtemplates-select-unsaved { .select { - color: colors.$translatedBlue !important; + color: colors.$blue500 !important; } } @@ -440,7 +452,7 @@ display: flex; flex-direction: column; gap: 20px; - background-color: colors.$grey5; + background-color: colors.$grey50; border-radius: 16px; } @@ -458,7 +470,6 @@ .dropdown__search-bar { height: 34px; margin: 0 12px 12px; - border-radius: 4px; border: 1px solid rgba(34, 36, 38, 0.15); background-color: white; @@ -484,7 +495,7 @@ } .dropdown__option--is-no-results-found { - color: colors.$grey7; + color: colors.$grey400; } .dropdown__option--is-no-results-found { @@ -494,12 +505,12 @@ .dropdown__option--is-active-option { background-color: unset; font-weight: bold; - background-color: colors.$grey5; + background-color: colors.$grey50; } .dropdown__option--is-highlighted-option, .dropdown__option:hover { - background-color: colors.$grey4; + background-color: colors.$grey100; } } @@ -509,7 +520,7 @@ input:not([type='radio']), textarea { - border: 1px solid colors.$grey2; + border: 1px solid colors.$grey300; border-radius: 4px; padding: 4px 8px; outline: none; @@ -517,7 +528,7 @@ line-height: 16px; &:focus, &:focus-visible { - border-color: colors.$linkBlueTransparent; + border-color: colors.$blue300; } } .dropdown__search-bar { @@ -536,3 +547,31 @@ margin-bottom: 0; } } + +.settings-panel-grey-button { + color: #000 !important; + background: colors.$grey100 !important; + padding: 4px 8px; + text-align: center; + border: 1px solid colors.$grey300 !important; + font-size: 14px !important; + + &:hover { + background-color: colors.$grey50 !important; + } +} + +.settings-panel-dropdownMenu { + z-index: 14; +} + +.project-template-dropdown-trigger-button { + color: white !important; + + &:hover, + &:focus { + background-color: unset !important; + box-shadow: inset 0 0 0 1px rgba(white, 0.6) !important; + color: rgba(white, 0.6) !important; + } +} diff --git a/public/css/sass/components/settingsPanel/SettingsPanelTable.scss b/public/css/sass/components/settingsPanel/SettingsPanelTable.scss index 108535a693..615a812762 100644 --- a/public/css/sass/components/settingsPanel/SettingsPanelTable.scss +++ b/public/css/sass/components/settingsPanel/SettingsPanelTable.scss @@ -1,4 +1,5 @@ @use '../../commons/colors'; +@use '../../commons/variables'; .settings-panel-table { position: relative; @@ -7,12 +8,12 @@ .settings-panel-button { cursor: pointer; color: colors.$black; - background: colors.$grey8; + background: colors.$grey200; border-radius: 2px 0 0 2px; padding: 6px 30px; - border: 1px solid colors.$grey; + border: 1px solid colors.$grey600; &:hover { - background-color: colors.$grey7; + background-color: colors.$grey400; } } .settings-panel-table-row-empty { @@ -24,11 +25,13 @@ .settings-panel-table-rowHeading { display: grid; align-items: center; - background-color: colors.$grey; + background-color: colors.$grey600; height: 30px; color: white; font-size: 15px; font-weight: bold; + border-top-left-radius: variables.$border-radius-default; + border-top-right-radius: variables.$border-radius-default; } .settings-panel-table-rowHeading-column { @@ -39,8 +42,6 @@ .settings-panel-row { display: flex; flex-direction: column; - border: 1px solid colors.$grey8; - border-bottom: unset; transition: padding 0.2s ease-out 0.15s; .settings-panel-cell-center { align-self: center; @@ -54,7 +55,7 @@ align-items: center; width: 100%; min-height: 50px; - background-color: colors.$grey9; + background-color: colors.$grey75; } .settings-panel-row-content > *:not(.settings-panel-row-drag-handle) { @@ -67,11 +68,7 @@ } .settings-panel-row-active { - background-color: colors.$transparentBlue; -} - -.settings-panel-row:last-child { - border-bottom: 1px solid colors.$grey8; + background-color: colors.$blue50; } .settings-panel-row-drag-handle { @@ -79,7 +76,7 @@ margin-left: 15px; margin-top: 8px; cursor: move; - border: 2px dotted #ccc; + border: 2px dotted colors.$grey200; border-top: 0; border-bottom: 0; width: 2px; @@ -154,3 +151,10 @@ padding: 5px 10px !important; font-size: 14px; } + +.settings-panel-table-rows-container { + overflow: hidden; + border: 1px solid colors.$grey200; + border-bottom-left-radius: variables.$border-radius-default; + border-bottom-right-radius: variables.$border-radius-default; +} diff --git a/public/css/sass/components/settingsPanel/TranslationMemoryGlossaryTab.scss b/public/css/sass/components/settingsPanel/TranslationMemoryGlossaryTab.scss index 0860d057a9..786aba47a6 100644 --- a/public/css/sass/components/settingsPanel/TranslationMemoryGlossaryTab.scss +++ b/public/css/sass/components/settingsPanel/TranslationMemoryGlossaryTab.scss @@ -1,4 +1,5 @@ @use '../../commons/colors'; +@use '../../commons/variables'; .translation-memory-glossary-tab { display: flex; @@ -32,8 +33,8 @@ display: flex; flex-direction: column; gap: 10px; - border-radius: 4px; - border: 1px dashed colors.$grey8; + border-radius: variables.$border-radius-default; + border: 1px dashed colors.$grey200; padding: 10px; margin-bottom: 20px; background: colors.$white; @@ -61,7 +62,7 @@ .translation-memory-glossary-tab-input-text { border-radius: 2px; - border: 1px solid colors.$grey8; + border: 1px solid colors.$grey200; padding: 6px; width: 350px; } @@ -119,7 +120,7 @@ .settings-panel-row-active { padding: 10px; - background-color: colors.$transparentBlue; + background-color: colors.$blue50; } .settings-panel-table-rowHeading-column { @@ -170,10 +171,10 @@ .tm-key-row-name { width: 100%; - padding: 4px; + padding: 4px 8px; background-color: unset; - border: 1px solid colors.$grey8; - border-radius: 3px; + border: 1px solid colors.$grey200; + border-radius: variables.$border-radius-default; &:focus, &:hover { @@ -194,7 +195,7 @@ } .tm-key-row-button-item { - color: colors.$grey6; + color: colors.$grey700; > :first-child { display: flex; @@ -204,8 +205,27 @@ } .tm-key-row-menu-button { + justify-content: unset; + .menu-button-wrapper { - > :first-child { + button { + color: colors.$black !important; + background: colors.$grey100 !important; + text-align: center; + border: 1px solid colors.$grey300 !important; + height: 32px !important; + font-size: 14px !important; + + &:hover { + background-color: colors.$grey50 !important; + } + } + + > :last-child { + padding: 4px 8px; + } + + /* > :first-child { min-width: 140px; border-radius: 2px; height: 28px; @@ -214,35 +234,36 @@ > :last-child { border: none; background-color: unset; - color: colors.$grey6; - } + color: colors.$grey700; + } */ } .just-button-import-tmx { min-width: 140px; border-radius: 2px; font-size: 16px; - color: #000; - background: colors.$grey4; + color: colors.$black; + background: colors.$grey100; padding: 4px 8px; text-align: center; - border: 1px solid colors.$grey7; + border: 1px solid colors.$grey400; &:hover { - background-color: colors.$grey5; + background-color: colors.$grey50; } } } -.tm-key-row-menu-button-dropdown { - margin-left: -10px; +.tm-key-row-options-menu-container { + display: flex; + gap: 8px; } .tm-key-row-icons { display: flex; align-items: center; justify-content: center; - color: colors.$grey; + color: colors.$grey600; } .translation-memory-glossary-tab-buttons-group { @@ -255,10 +276,10 @@ width: 100%; padding: 4px; border-radius: 3px; - border: solid 1px colors.$grey3; + border: solid 1px colors.$grey150; &.error { - border: solid 1px colors.$redDefault; + border: solid 1px colors.$red500; } } @@ -267,7 +288,7 @@ .translation-memory-glossary-tab-delete { display: flex; flex-direction: column; - padding: 10px; + padding: 10px 35px 10px 10px; min-height: 50px; .action-form { @@ -276,7 +297,7 @@ align-items: center; width: 100%; .translation-memory-glossary-tab-label { - gap: 220px !important; + gap: 200px !important; } > :first-child { display: flex; @@ -301,7 +322,7 @@ } .action-form-error { input { - color: colors.$redDefault; + color: colors.$red500; } } @@ -328,12 +349,12 @@ } .filename-error { - color: colors.$redDefault; + color: colors.$red500; } } > li:nth-child(even) { - background-color: colors.$grey4; + background-color: colors.$grey100; } } @@ -341,24 +362,24 @@ width: 260px; height: 6px; border-radius: 4px; - background-color: colors.$grey8; + background-color: colors.$grey200; > :first-child { - background-color: colors.$approvedGreen; + background-color: colors.$green800; height: 100%; border-radius: 4px; } } .import-completed { - color: colors.$approvedGreenHover; + color: colors.$green600; } .message-error { display: flex; align-items: center; gap: 8px; - color: colors.$redDefault; + color: colors.$red500; > button { padding: 4px; @@ -373,7 +394,7 @@ margin-top: 6px; > :last-child { - color: colors.$approvedGreenHover; + color: colors.$green600; } } } @@ -385,8 +406,8 @@ } .translation-memory-glossary-tab-delete { - border-top: 3px solid #ffcc01; - background-color: colors.$orangeDefaultTransparent2; + border-top: 3px solid colors.$orange200; + background-color: colors.$orange50; } .translation-memory-glossary-tab-active-table { @@ -406,8 +427,8 @@ .settings-panel-row-dragover-half-bottom ) { .settings-panel-row-active { - border-bottom-left-radius: 8px; - border-bottom-right-radius: 8px; + border-bottom-left-radius: variables.$border-radius-default; + border-bottom-right-radius: variables.$border-radius-default; } } } @@ -418,9 +439,9 @@ justify-content: space-between; height: 56px; padding: 20px; - background-color: colors.$grey3; - border-top-left-radius: 8px; - border-top-right-radius: 8px; + background-color: colors.$grey150; + border-top-left-radius: variables.$border-radius-default; + border-top-right-radius: variables.$border-radius-default; } .tm-prioritization-text-content { @@ -434,32 +455,17 @@ } span { - color: colors.$grey6; + color: colors.$grey700; } } .switch-container-outer { - width: 155px; + width: 150px; } } +.tm-key-row-menu-button, .tm-row-penalty { - .tm-row-penalty-button, - .penalty-numeric-stepper-close-button { - border-radius: 2px; - font-size: 16px; - color: #000 !important; - background: colors.$grey4 !important; - padding: 4px 8px; - text-align: center; - border: 1px solid colors.$grey7 !important; - font-size: 16px !important; - - &:hover { - background-color: colors.$grey5 !important; - } - } - .tm-row-penalty-numeric-stepper { display: flex; gap: 5px; @@ -468,7 +474,7 @@ .penalty-numeric-stepper-close-button { width: 28px !important; height: 28px !important; - color: colors.$grey6 !important; + color: colors.$grey700 !important; } } diff --git a/public/css/sass/components/signin/ForgotPassword.scss b/public/css/sass/components/signin/ForgotPassword.scss index 1d0bade6b3..0a5cb667a0 100644 --- a/public/css/sass/components/signin/ForgotPassword.scss +++ b/public/css/sass/components/signin/ForgotPassword.scss @@ -19,7 +19,7 @@ } p { - color: colors.$grey7; + color: colors.$grey400; } .forgotpassword-form { diff --git a/public/css/sass/components/signin/Login.scss b/public/css/sass/components/signin/Login.scss index ff85adff47..1fc6b3775c 100644 --- a/public/css/sass/components/signin/Login.scss +++ b/public/css/sass/components/signin/Login.scss @@ -47,7 +47,7 @@ flex-direction: column; gap: 30px; font-size: 16px; - color: colors.$grey7; + color: colors.$grey400; > :first-child { display: flex; diff --git a/public/css/sass/components/signin/OnBoarding.scss b/public/css/sass/components/signin/OnBoarding.scss index d43753e348..6b97d96719 100644 --- a/public/css/sass/components/signin/OnBoarding.scss +++ b/public/css/sass/components/signin/OnBoarding.scss @@ -27,7 +27,7 @@ } p { - color: colors.$grey7; + color: colors.$grey400; } @@ -54,14 +54,14 @@ height: 20px; line-height: 20px; border-radius: 50%; - background-color: colors.$grey7; + background-color: colors.$grey400; color: colors.$white; } } } .form-errorMessage { font-size: 14px; - color: colors.$redDefault; + color: colors.$red500; text-align: center; padding-left: 2px; } diff --git a/public/css/sass/components/signin/PasswordReset.scss b/public/css/sass/components/signin/PasswordReset.scss index 74a89f158c..16bbb73c8f 100644 --- a/public/css/sass/components/signin/PasswordReset.scss +++ b/public/css/sass/components/signin/PasswordReset.scss @@ -19,7 +19,7 @@ } p { - color: colors.$grey7; + color: colors.$grey400; } .passwordreset-form { diff --git a/public/css/sass/components/signin/Register.scss b/public/css/sass/components/signin/Register.scss index c1cd7c8dbe..91bfbb5e23 100644 --- a/public/css/sass/components/signin/Register.scss +++ b/public/css/sass/components/signin/Register.scss @@ -1,4 +1,5 @@ @use '../../commons/colors'; +@use '../../commons/variables'; .register-component { display: flex; @@ -10,8 +11,8 @@ flex-direction: column; gap: 20px; max-width: 320px; - background: #f5f6f7; - border-radius: 8px; + background: colors.$grey50; + border-radius: variables.$border-radius-default; padding: 64px 40px; h2, @@ -31,7 +32,7 @@ svg { flex-shrink: 0; - color: colors.$translatedBlue; + color: colors.$blue500; } } } @@ -51,14 +52,14 @@ h4 { font-size: 16px; font-weight: bold; - color: colors.$grey7; + color: colors.$grey400; text-align: center; margin: 0; } } .register-divider { - color: colors.$grey7; + color: colors.$grey400; display: flex; align-items: center; width: 100%; @@ -66,7 +67,7 @@ div { flex-grow: 1; height: 1px; - background-color: colors.$grey8; + background-color: colors.$grey200; } span { @@ -101,7 +102,7 @@ > span { display: flex; - color: colors.$grey7; + color: colors.$grey400; } } } @@ -109,7 +110,7 @@ .terms-and-conditions-error { font-size: 12px; text-align: left; - color: colors.$redDefault; + color: colors.$red500; } } @@ -117,7 +118,7 @@ display: flex; justify-content: center; font-size: 16px; - color: colors.$grey7; + color: colors.$grey400; } } @@ -140,7 +141,7 @@ } p { - color: colors.$grey7; + color: colors.$grey400; } .footer-buttons { @@ -153,6 +154,6 @@ .email-sent-again { text-align: center; - color: colors.$grey7; + color: colors.$grey400; } } diff --git a/public/css/sass/lexiqa.scss b/public/css/sass/lexiqa.scss index caa5198b7e..a15f9b3b5f 100755 --- a/public/css/sass/lexiqa.scss +++ b/public/css/sass/lexiqa.scss @@ -1,3 +1,4 @@ +@use './commons/colors'; /* ============================== Tooltip STYLING @@ -33,14 +34,14 @@ } } .tooltip-error-ignore { - color: #757575; + color: colors.$grey600; text-decoration: none; cursor: pointer; border-radius: 0 4px 4px 0; padding-left: 10px; height: 40px; &:hover { - color: #525252; + color: colors.$grey700; } .icon-cancel-circle:before { line-height: 40px; @@ -81,27 +82,27 @@ } .n0 { - background-color: #d08053; + background-color: colors.$orange500; } .p0 { - background-color: #65c783; + background-color: colors.$green300; } .c0 { - background-color: #65c783; + background-color: colors.$green300; } .u0 { - background-color: #b8a300; + background-color: colors.$orange600; } .s0 { - background-color: #38c0c5; + background-color: colors.$blue200; } .l0 { - background-color: #b792e6; + background-color: colors.$purple200; } .b0 { @@ -117,11 +118,11 @@ } .o0 { - background-color: rgba(#209faa, 0.75); + background-color: rgba(colors.$blue200, 0.75); } .m { - background-color: #ea92b8; + background-color: colors.$red100; } .m, diff --git a/public/css/sass/mbc-style.scss b/public/css/sass/mbc-style.scss index e4d7340f14..921d90961c 100644 --- a/public/css/sass/mbc-style.scss +++ b/public/css/sass/mbc-style.scss @@ -1,4 +1,5 @@ @use 'commons/colors'; +@use 'commons/variables'; /* ****** ****** @@ -8,7 +9,7 @@ */ .mbc-comment-balloon-inner { - background: #ffffff; + background: colors.$white; box-shadow: 0 1px 2px 0px rgba(0, 0, 0, 0.3); } @@ -36,26 +37,7 @@ */ .mbc-thread-wrap { padding: 10px; - border-top: 1px solid #f2f4f7; -} - -/* - ****** - Past comment thread wrap status active in history balloon - ****** - */ -.mbc-history-balloon .mbc-thread-wrap-active { - border-bottom: 2px solid #dadada; -} - -/* - ****** - Past comment thread wrap status resolved - ****** - */ -.mbc-thread-wrap-resolved { - background: rgba(124, 197, 118, 0.15); - border-bottom: 2px solid rgba(124, 197, 118, 0.6); /* $approvedGreen */ + border-top: 1px solid colors.$grey50; } /* @@ -68,7 +50,7 @@ } .mbc-comments-wrap .mbc-show-comment:not(:last-of-type) { - background-color: colors.$grey5; + background-color: colors.$grey50; border-radius: 4px; padding: 8px; > .bc-show-comment-top { @@ -80,7 +62,7 @@ .mbc-comments-wrap .mbc-thread-wrap-resolved .mbc-show-comment:not(:last-of-type) { - background-color: rgba(colors.$greenDefaultTransparent, 0.2); + background-color: rgba(colors.$green300, 0.2); border-radius: 4px; } @@ -95,7 +77,7 @@ } .mbc-comment-info { - color: #7f7f7f; + color: colors.$grey600; display: inline-block; font-size: 11px; font-weight: lighter; @@ -106,7 +88,7 @@ Message past comment details */ .mbc-comment-body { - color: #323232; + color: colors.$grey1300; font-size: 14px; margin: 12px 0 16px; word-wrap: break-word; @@ -130,10 +112,10 @@ position: relative; word-break: normal; outline: none; - color: #000; - border: 1px solid #dedede; - box-shadow: inset 0 1px 2px #ccc; - -webkit-box-shadow: inset 0 1px 2px #ccc; + color: colors.$black; + border: 1px solid colors.$grey200; + box-shadow: inset 0 1px 2px colors.$grey200; + -webkit-box-shadow: inset 0 1px 2px colors.$grey200; min-height: 40px; overflow-y: auto !important; max-height: 160px; @@ -153,15 +135,15 @@ box-shadow: none; } .mbc-comment-textarea:focus { - border: 1px solid #96c8da; - box-shadow: inset 0px 0px 2px 2px #96c8da; + border: 1px solid colors.$grey300; + box-shadow: inset 0px 0px 2px 2px colors.$grey300; padding-top: 10px; padding-bottom: 10px; } .mbc-comment-textarea:empty:not(:focus):before { content: attr(data-placeholder); - color: #999; + color: colors.$grey400; position: absolute; top: 10px; pointer-events: none; @@ -173,25 +155,25 @@ .mbc-comment-input__suggestions__list { background-color: colors.$white; - border: 1px solid colors.$grey8; + border: 1px solid colors.$grey200; } .mbc-comment-input__suggestions__item { padding: 5px 15px; - border-bottom: 1px solid colors.$grey9; + border-bottom: 1px solid colors.$grey75; } .mbc-comment-input__suggestions__item--focused { - background-color: rgba(colors.$grey9, 0.6); - color: colors.$translatedBlue; + background-color: rgba(colors.$grey75, 0.6); + color: colors.$blue500; } .tagging-item { - color: colors.$translatedBlue; + color: colors.$blue500; } .tagging-item-textarea { - background-color: rgba(colors.$translatedBlue, 0.3); + background-color: rgba(colors.$blue500, 0.3); border-radius: 10px; padding: 2px 0; } @@ -218,12 +200,12 @@ Username label */ .mbc-comment-username-label { - color: #323232; + color: colors.$grey1300; font-weight: bold; margin-bottom: 4px; padding: 5px 5px 2px 0; span { - color: colors.$grey7; + color: colors.$grey400; } } /* @@ -248,7 +230,7 @@ } .mbc-comment-resolved-label { - color: colors.$approvedGreen; /* per-green line 2350 style.css */ + color: colors.$green800; /* per-green line 2350 style.css */ font-size: 12px; font-weight: bold; } @@ -266,7 +248,7 @@ a.ui.button.mbc-comment-delete-btn { */ a.mbc-comment-link-btn, a.mbc-comment-link-btn:visited { - color: #7f7f7f; + color: colors.$grey600; display: inline-block; font-size: 14px; text-decoration: underline; @@ -284,7 +266,7 @@ a.mbc-comment-link-btn:active { */ a.mbc-view-link:link, a.mbc-view-link:visited { - color: #0798bc; + color: colors.$blue600; padding: 0 4px 6px 0; } @@ -295,9 +277,9 @@ a.mbc-view-link:visited { */ .mbc-nth-comment-label { display: block; - border-bottom: 1px solid #cccccc; + border-bottom: 1px solid colors.$grey200; font-size: 16px; - color: #9a9a9a; + color: colors.$grey400; line-height: 1.8; margin-bottom: 6px; } @@ -338,7 +320,7 @@ a.mbc-view-link:visited { gap: 6px; align-self: stretch; cursor: pointer; - border-radius: 8px; + border-radius: variables.$border-radius-default; width: 18px; height: 18px; color: black; @@ -356,15 +338,15 @@ a.mbc-view-link:visited { Highlight element unique properties */ .mbc-comment-highlight { - background: #ffe400; + background: colors.$orange200; } /* Invitation element unique properties */ .mbc-comment-highlight-invite { - background: colors.$darkBlue; - color: colors.$grey3; + background: colors.$blue900; + color: colors.$grey150; position: absolute; } @@ -396,7 +378,7 @@ article .mbc-comment-balloon-outer { } /* Warnings style.css line 136 */ .mbc-warnings { - color: #d65959; + color: colors.$red400; font-size: 14px; } @@ -408,97 +390,6 @@ article .mbc-comment-balloon-outer { ****** */ -#mbc-history { - cursor: pointer; - font-size: 23px; - height: 27px; - padding-top: 12px; - position: relative; - text-align: center; - width: 45px; - &.open svg { - opacity: 1; - } - &.mbc-history-balloon-icon-has-no-comments { - opacity: 0.4; - cursor: default; - pointer-events: none; - } -} - -#mbc-history:hover { - color: #ccc; -} - -.mbc-badge-container { - position: absolute; - top: -3px; - right: -4px; - display: flex; - .mbc-badge, - .mbc-badge-resolved { - padding: 1px 6px; - background: #0bbeec; - color: #fff; - font-size: 10px; - text-align: center; - border-radius: 25px; - vertical-align: middle; - line-height: 16px; - height: 17px; - display: block; - } - .mbc-badge-resolved { - background-color: colors.$greenDefaultTransparent; - } -} - -/* - ****** - ****** - History ballon - ****** - ****** - */ - -.mbc-history-balloon-outer { - background-color: rgba(247, 247, 247, 1); /* #f7f77f */ - box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3); - margin-top: 20px; - padding-top: 10px; - position: absolute; - right: 10px; - width: 300px; - text-align: left; -} - -.mbc-view-comment-wrap { - margin-bottom: 10px; -} - -.mbc-history-balloon { - background-color: rgba(247, 247, 247, 1); /* #ffffff */ - padding: 0; - position: relative; -} - -.mbc-history-balloon .mbc-thread-wrap { - padding: 14px 0; -} - -.mbc-history-balloon .mbc-show-comment { - padding: 0 24px; -} - -.mbc-history-balloon .mbc-thread-wrap:not(:last-of-type) .mbc-show-comment { - /*border-bottom: 1px solid #dadada;*/ -} - -.mbc-history-balloon-has-comment { - max-height: 500px; - overflow-y: auto; -} - /* Truncate text in label */ @@ -511,8 +402,7 @@ article .mbc-comment-balloon-outer { /* Set box model to border and account for border's width */ -.mbc-comment-balloon-outer *, -.mbc-history-balloon-outer * { +.mbc-comment-balloon-outer * { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; @@ -532,7 +422,7 @@ article .mbc-comment-balloon-outer { Triangle top top in history balloon */ .mbc-triangle-top { - border-right: 14px solid rgba(247, 247, 247, 1); /* #f7f77f */ + border-right: 14px solid colors.$grey50; /* #f7f77f */ border-top: 14px solid transparent; -webkit-filter: drop-shadow(-3px -1px 2px rgba(0, 0, 0, 0.1)); filter: drop-shadow(-3px -1px 2px rgba(0, 0, 0, 0.1)); @@ -545,7 +435,7 @@ article .mbc-comment-balloon-outer { Triangle top left in comment balloon */ .mbc-triangle-topleft { - border-top: 12px solid #ffffff; + border-top: 12px solid colors.$white; border-left: 14px solid transparent; -webkit-filter: drop-shadow(-1px 0px 0px rgba(0, 0, 0, 0.2)); filter: drop-shadow(-1px 0px 0px rgba(0, 0, 0, 0.2)); @@ -559,7 +449,7 @@ section.editor .mbc-triangle.mbc-triangle-topleft { } .mbc-open-view { - border-top: 12px solid #ffffff; + border-top: 12px solid colors.$white; border-left: 14px solid transparent; -webkit-filter: drop-shadow(-1px 0px 0px rgba(0, 0, 0, 0.2)); filter: drop-shadow(-2px 0px 1px rgba(0, 0, 0, 0.2)); @@ -571,7 +461,7 @@ section.editor .mbc-triangle.mbc-triangle-topleft { bottom: 0px; border-top: unset; border-left: unset; - border-bottom: 12px solid #ffffff; + border-bottom: 12px solid colors.$white; border-left: 14px solid transparent; filter: drop-shadow(-1px 2px 1px rgba(0, 0, 0, 0.2)); } @@ -585,18 +475,18 @@ Close icon ballon - Right panel .re-close-balloon { width: 24px; height: 24px; - background: #fff; + background: colors.$white; position: absolute; z-index: 1; right: 0px; top: -14px; border-radius: 50%; - color: #7b7b7b; + color: colors.$grey600; cursor: pointer; } .re-close-balloon:hover { - color: #000000; + color: colors.$black; } .re-close-balloon i { @@ -661,7 +551,7 @@ section:hover .mbc-comment-icon-button, align-items: center; padding: 8px 4px; .input-checkbox > span { - color: colors.$grey7; + color: colors.$grey400; font-size: 14px; } } diff --git a/public/css/sass/modals/PreferenceModal.scss b/public/css/sass/modals/PreferenceModal.scss index a680e83d3e..230d0e44a7 100644 --- a/public/css/sass/modals/PreferenceModal.scss +++ b/public/css/sass/modals/PreferenceModal.scss @@ -22,7 +22,7 @@ > label { font-size: 15px; - color: colors.$grey1; + color: colors.$grey500; } } @@ -55,7 +55,7 @@ font-size: 15px; text-align: left; word-wrap: break-word; - color: colors.$grey1; + color: colors.$grey500; white-space: nowrap; width: 100%; border: none; @@ -83,8 +83,8 @@ flex: 1 100%; line-height: 40px; margin-top: 13px; - border: 1px solid colors.$greenDefault; - background-color: #f7fdf7; + border: 1px solid colors.$green500; + background-color: colors.$white; border-radius: 4px; display: flex; justify-content: center; @@ -92,7 +92,7 @@ padding: 10px; i { - color: colors.$greenDefault; + color: colors.$green500; margin-top: 8px; margin-left: 20px; } @@ -132,7 +132,7 @@ line-height: 25px; .user-info-icon-update { cursor: pointer; - color: colors.$grey; + color: colors.$grey600; &:hover { color: colors.$black; } @@ -177,10 +177,10 @@ line-height: 50px; text-align: center; font-size: 21px; - color: #fff; + color: colors.$white; padding: 0; - background: #b7b7b7; - border: 1px solid #ccc; + background: colors.$grey400; + border: 1px solid colors.$grey200; -moz-border-radius: 50px; -webkit-border-radius: 50px; border-radius: 50px; @@ -206,14 +206,14 @@ .button { font-family: Calibri, Arial, Helvetica, sans-serif; vertical-align: top; - border: 1px solid #797979; + border: 1px solid colors.$grey600; border-radius: 2px; font-size: 16px; margin-bottom: 15px; margin-left: 80%; - background-color: colors.$translatedBlue; + background-color: colors.$blue500; transition: 0.3s ease; - color: #ffffff; + color: colors.$white; text-shadow: none; background-image: none; cursor: pointer; @@ -228,9 +228,9 @@ text-decoration: none; user-select: none; &:hover { - background-color: #08b3de; + background-color: colors.$blue200; box-shadow: - 0 0 0 #e0e0e0, + 0 0 0 colors.$grey200, 0 0 2px rgba(0, 0, 0, 0.12), 0 2px 4px rgba(0, 0, 0, 0.24) !important; } @@ -238,6 +238,6 @@ } .user-info-form .grey-txt { - color: colors.$grey1; + color: colors.$grey500; } diff --git a/public/css/sass/modals/instructionsModal.scss b/public/css/sass/modals/instructionsModal.scss index e9ff93750d..887191c25c 100644 --- a/public/css/sass/modals/instructionsModal.scss +++ b/public/css/sass/modals/instructionsModal.scss @@ -1,18 +1,11 @@ +@use '../commons/colors'; +@use '../commons/variables'; .instructions-modal { min-height: 230px; max-width: 900px; h2 { padding-top: 16px; } - - span.fileFormat { - padding: 4px 5px 4px 47px; - background-size: 25px !important; - line-height: 25px; - white-space: nowrap; - text-overflow: ellipsis; - overflow: hidden; - } .ui.accordion { max-height: 400px; overflow: auto; @@ -33,15 +26,15 @@ .title { display: flex; align-items: center; - color: #666; + color: colors.$grey700; &:hover { - color: #000; + color: colors.$black; } &.current { //color: #fff; - background: #dee4ea; + background: colors.$grey150; &:hover { - background: #d9e0e8; + background: colors.$grey150; //color: #fff; } .current-icon { @@ -62,7 +55,7 @@ } } .instructions-container { - background-color: #fff; + background-color: colors.$white; padding: 20px; margin-top: 20px; margin-bottom: 20px; @@ -73,7 +66,7 @@ word-break: break-all; } blockquote { - border-left: 5px solid #ccc; + border-left: 5px solid colors.$grey200; margin: 1.5em 10px; padding: 0.5em 10px; } @@ -91,7 +84,7 @@ &:not(:first-child) { .accordion-component-title { - border-top: solid 1px #aebdcd; + border-top: solid 1px colors.$grey300; } &:has(.accordion-expanded) { @@ -109,13 +102,15 @@ &:first-child { .accordion-component-title { - border-radius: 8px 8px 0 0 !important; + border-radius: variables.$border-radius-default + variables.$border-radius-default 0 0 !important; } } &:last-child { .accordion-component-title:not(.accordion-expanded) { - border-radius: 0 0 8px 8px !important; + border-radius: 0 0 variables.$border-radius-default + variables.$border-radius-default !important; } } @@ -133,7 +128,7 @@ &:not(:first-child) { .accordion-component-title { - border-top: solid 1px #aebdcd; + border-top: solid 1px colors.$grey300; } &:has(.accordion-expanded) { @@ -151,13 +146,15 @@ &:first-child { .accordion-component-title { - border-radius: 8px 8px 0 0 !important; + border-radius: variables.$border-radius-default + variables.$border-radius-default 0 0 !important; } } &:last-child { .accordion-component-title { - border-radius: 0 0 8px 8px !important; + border-radius: 0 0 variables.$border-radius-default + variables.$border-radius-default !important; } } @@ -175,7 +172,7 @@ &:not(:first-child) { .accordion-component-title { - border-top: solid 1px #aebdcd; + border-top: solid 1px colors.$grey300; } &:has(.accordion-expanded) { @@ -193,13 +190,15 @@ &:first-child { .accordion-component-title { - border-radius: 8px 8px 0 0 !important; + border-radius: variables.$border-radius-default + variables.$border-radius-default 0 0 !important; } } &:last-child { .accordion-component-title:not(.accordion-expanded) { - border-radius: 0 0 8px 8px !important; + border-radius: 0 0 variables.$border-radius-default + variables.$border-radius-default !important; } } @@ -211,7 +210,7 @@ &:first-child:nth-last-child(1) { .accordion-component-title:not(.accordion-expanded) { - border-radius: 8px !important; + border-radius: variables.$border-radius-default !important; } } } diff --git a/public/css/sass/modals/language-selector.scss b/public/css/sass/modals/language-selector.scss index c5fcd03812..4af92dbd04 100644 --- a/public/css/sass/modals/language-selector.scss +++ b/public/css/sass/modals/language-selector.scss @@ -2,21 +2,21 @@ @use "../commons/colors"; #matecat-modal-languages { - $light-blue: colors.$translatedBlue; - $medium-blue: colors.$linkBlue; - $dark-blue: colors.$darkBlue; + $light-blue: colors.$blue500; + $medium-blue: colors.$blue700; + $dark-blue: colors.$blue900; $placeholder-gray: #cdd4de; - $btn-shadow-gray: colors.$grey1; - $btn-hover-blue: colors.$translatedBlueHover; + $btn-shadow-gray: colors.$grey500; + $btn-hover-blue: colors.$blue600; - $medium-gray: colors.$grey2; - $dark-gray: colors.$grey1; + $medium-gray: colors.$grey300; + $dark-gray: colors.$grey500; /* Modal */ .matecat-modal { button:focus { - border: 1px solid colors.$translatedBlue; + border: 1px solid colors.$blue500; } } @@ -34,15 +34,11 @@ display: flex; justify-content: space-between; align-items: center; - - .close-matecat-modal { - padding-bottom: 9px; - } } /* Modal Subheader */ .matecat-modal-subheader { - background: #fff; + background: colors.$white; border-bottom: 1px solid $medium-gray; /*height: $subheader-height;*/ padding: 16px 16px 16px 32px; @@ -61,7 +57,7 @@ } .label { - color: colors.$grey6; + color: colors.$grey700; margin: 0px 8px 0 0; } @@ -71,13 +67,13 @@ gap: 5px; .list-badge { - background-color: colors.$grey1; + background-color: colors.$grey500; border-radius: 12px; padding: 2px 10px; cursor: pointer; &:hover { - background-color: colors.$darkBlueHover; + background-color: colors.$blue950; } .language-name { @@ -156,8 +152,8 @@ text-transform: capitalize; border-radius: 2px; margin: 0 2px; - background: #fff; - color: #000; + background: colors.$white; + color: colors.$black; border: 1px solid $medium-gray; &:hover { cursor: default; @@ -170,9 +166,9 @@ } &.highlightDelete { background: $light-blue; - color: #ffffff; + color: colors.$white; .react-tagsinput-remove { - color: #ffffff; + color: colors.$white; } } } @@ -204,7 +200,7 @@ .matecat-modal-footer { overflow: auto; height: 72px; - background: #fff; + background: colors.$white; border-top: 1px solid $medium-gray; padding: 8px 16px 8px 32px; @@ -228,10 +224,10 @@ /* Badge */ .badge { padding: 0.35rem 0.58rem; - background: colors.$translatedBlue; + background: colors.$blue500; border-radius: 25px; font-size: 0.9rem; - color: #fff; + color: colors.$white; line-height: 1; } @@ -272,7 +268,7 @@ &.selected { background: $dark-blue; - color: #fff; + color: colors.$white; } &:not(.selected) .check { display: none; @@ -296,7 +292,7 @@ &:hover:not(.selected), &.hover:not(.selected) { - background: colors.$grey3; + background: colors.$grey150; color: $medium-blue; // padding-left: 26px; @@ -308,60 +304,10 @@ .language-dropdown-item-container { .code-badge-selected { background-color: colors.$white; - color: colors.$darkBlue; + color: colors.$blue900; } } } } } - - /* Buttons */ - - .modal-btn { - padding: 8px 16px; - border-radius: 2px; - margin: 4px 8px; - cursor: pointer; - - &:focus { - outline: none; - } - - &.primary { - min-width: 128px; - //-webkit-box-shadow: 0 2px 8px 0 $btn-shadow-gray; - //-moz-box-shadow: 0 2px 8px 0 $btn-shadow-gray; - //box-shadow: 0 2px 8px 0 $btn-shadow-gray; - } - - &.secondary { - min-width: 100px; - } - - &.blue { - background: $light-blue; - border: 1px solid $light-blue; - color: #fff; - &:hover { - background-color: $btn-hover-blue; - //box-shadow: 0 0 0 #e0e0e0, 0 0 2px rgba(0, 0, 0, 0.12), 0 2px 4px rgba(0, 0, 0, 0.24) !important; - } - &:focus { - box-shadow: none; - border: 1px solid $dark-blue; - } - } - - &.gray { - background: #fff; - color: #000; - border: 1px solid $medium-gray; - &:focus { - border: 1px solid $light-blue; - } - &:hover { - background-color: colors.$grey3; - } - } - } } diff --git a/public/css/sass/modals/split_modal.scss b/public/css/sass/modals/split_modal.scss index 8883be5ac5..96abe1f223 100644 --- a/public/css/sass/modals/split_modal.scss +++ b/public/css/sass/modals/split_modal.scss @@ -11,7 +11,7 @@ top: 0; border-radius: 0 0 4px 4px; text-align: left; - border: 1px solid #666; + border: 1px solid colors.$grey700; min-width: 670px; } .splitbtn-cont { @@ -21,7 +21,7 @@ .popup-split-job-id { font-weight: 100; font-size: 16px; - color: colors.$grey1; + color: colors.$grey500; margin-right: 5px; } } @@ -32,7 +32,7 @@ margin-right: 15px !important; font-size: 18px; text-align: right; - color: #d65757 !important; + color: colors.$red400 !important; display: block; line-height: 13px !important; } @@ -45,7 +45,7 @@ .splitbtn-cont { overflow: hidden; font-size: 18px; - color: colors.$grey1; + color: colors.$grey500; font-weight: bold; display: flex; flex-direction: column; @@ -71,7 +71,7 @@ .nosplit { float: right; font-size: 20px; - color: colors.$grey1; + color: colors.$grey500; display: none; margin: 45px 140px 0 0; } @@ -83,7 +83,7 @@ } input[type='text'][disabled] { - background: #f0f0f0; + background: colors.$grey75; } h2 { @@ -97,7 +97,7 @@ h3 { font-size: 20px !important; font-weight: bold !important; - color: #333 !important; + color: colors.$grey1300 !important; display: inline-block; vertical-align: text-top; } @@ -114,9 +114,9 @@ width: auto; height: 37px; padding: 4px; - color: colors.$grey1; + color: colors.$grey500; font-size: 18px; - border: 1px solid colors.$grey1; + border: 1px solid colors.$grey500; box-sizing: border-box; display: inline-block; background: white; @@ -153,8 +153,8 @@ cursor: default; -moz-box-shadow: none; -webkit-box-shadow: none; - border: 1px solid colors.$grey1; - background: #ccc; + border: 1px solid colors.$grey500; + background: colors.$grey200; } .split-box2 { @@ -167,12 +167,12 @@ left: 50%; margin: -300px 0 0 -350px; z-index: 999999; - background: #fff; - box-shadow: 0px 0px 25px #000; + background: colors.$white; + box-shadow: 0px 0px 25px colors.$black; border-radius: 2px; text-align: left; font-size: 18px; - border: 1px solid colors.$grey1; + border: 1px solid colors.$grey500; } .split-box3 .input, .split-box2 .input { @@ -201,12 +201,12 @@ margin-right: 0px; padding: 6px 5px 5px 5px; font-size: 18px; - background: #fdfdfd; + background: colors.$white; background-size: 13px 11px; box-sizing: content-box; - border: 1px solid #ccc; + border: 1px solid colors.$grey200; border-radius: 6px; - box-shadow: inset 0 1px 3px #ddd; + box-shadow: inset 0 1px 3px colors.$grey200; } .btn-cancel { @@ -219,7 +219,7 @@ padding: 0px; width: 99%; border-radius: 0px; - background: #ffffff; + background: colors.$white; //box-shadow: 0 0 0 #e0e0e0, 0 0 2px rgba(0, 0, 0, 0.12), 0 2px 4px rgba(0, 0, 0, 0.24) !important; } @@ -231,31 +231,31 @@ width: 82%; margin: 25px 0 -20px 20px; text-align: right; - color: #ff0000; + color: colors.$red500; font-size: 12px; } .error-message { - background: #d65757; - color: #fff; + background: colors.$red400; + color: colors.$white; margin: 0 0 10px 0; float: left; font-weight: bold; width: 100%; -moz-border-radius: 2px; border-radius: 2px; - border: 1px solid #c45f5f; + border: 1px solid colors.$orange500; margin-top: 10px; } .error { margin-right: auto; - color: #ff0000;; + color: colors.$red500; } .jobcontainer { padding-bottom: 50px; - border-bottom: 1px dashed #ccc; + border-bottom: 1px dashed colors.$grey200; } div.wrapper div:last-child { @@ -289,12 +289,12 @@ float: right; } .job-perc { - color: #999; + color: colors.$grey400; margin: 0; float: left; padding: 10px; font-size: 18px; - color: #000; + color: colors.$black; text-align: right; } .job-perc p { @@ -307,7 +307,7 @@ .total .wordsum { font-size: 20px; - color: colors.$grey1; + color: colors.$grey500; text-align: right; margin-right: 15px; margin-top: 10px; @@ -326,8 +326,7 @@ cursor: default; -moz-box-shadow: none; -webkit-box-shadow: none; - border: 1px solid colors.$grey1; - background: #ccc !important; + background: colors.$grey200 !important; } .btn-cancel { @@ -346,7 +345,7 @@ .empty { border: 0 !important; - background: #f0f0f0 !important; + background: colors.$grey75 !important; width: 120px; } @@ -357,7 +356,7 @@ box-shadow: none; } &:focus { - border-color: #96c8da; + border-color: colors.$grey300; box-shadow: none; } } diff --git a/public/css/sass/modals/tmShareModal.scss b/public/css/sass/modals/tmShareModal.scss index 741cd960d8..b73e0eae0e 100644 --- a/public/css/sass/modals/tmShareModal.scss +++ b/public/css/sass/modals/tmShareModal.scss @@ -1,3 +1,4 @@ +@use '../commons/colors'; /*** Share Key Popup ***/ .share-popup-container { margin: 20px; @@ -35,7 +36,7 @@ .share-popup-container-list h3 { font-size: 18px; - background: #f4f4f4; + background: colors.$grey75; text-align: left; margin: 0 !important; margin: 0 !important; @@ -47,7 +48,7 @@ border: 0; text-align: center; width: 165px; - border-bottom: 1px dashed #ccc; + border-bottom: 1px dashed colors.$grey200; } .share-popup-input-key:focus { @@ -74,7 +75,7 @@ max-height: 300px; position: relative; float: left; - border: 1px solid #d5d5d5; + border: 1px solid colors.$grey200; border-radius: 4px; margin: 20px; } @@ -86,7 +87,7 @@ float: left; overflow-y: auto; overflow-x: hidden; - border-top: 1px solid #cacaca; + border-top: 1px solid colors.$grey200; box-shadow: inset 0 2px 2px -1px rgba(0, 0, 0, 0.1); -webkit-box-shadow: inset 0 2px 2px -1px rgba(0, 0, 0, 0.1); } @@ -115,8 +116,8 @@ input.share-popup-container-input-email { width: 344px; height: 34px; padding-left: 4px; - background-color: #fbfbfb; - border: 1px solid #ccc; + background-color: colors.$white; + border: 1px solid colors.$grey200; border-radius: 2px; } @@ -124,7 +125,7 @@ input.share-popup-container-input-email { width: 100%; height: 45px; float: left; - border-bottom: 1px solid #cacaca; + border-bottom: 1px solid colors.$grey200; } .share-popup-list-item:last-child { @@ -143,6 +144,6 @@ span.share-popup-item-name, span.share-popup-item-email { font-size: 14px; - color: #999; + color: colors.$grey400; line-height: 13px; } diff --git a/public/css/sass/popup.scss b/public/css/sass/popup.scss index 070030504b..15693688b8 100644 --- a/public/css/sass/popup.scss +++ b/public/css/sass/popup.scss @@ -9,7 +9,7 @@ //-webkit-box-shadow: 0 1px 20px #000; //box-shadow: 0 1px 20px #000; min-width: 600px; - background-color: colors.$grey5; + background-color: colors.$grey50; margin: -200px 0 0 -250px; padding: 0 0px 20px 0px; position: fixed; @@ -34,8 +34,8 @@ max-height: inherit; font-size: 24px; padding: 10px 10px 7px 58px; - border-bottom: 1px solid #000; - color: #fff; + border-bottom: 1px solid colors.$black; + color: colors.$white; margin: 0 !important; text-align: left; } @@ -66,47 +66,22 @@ padding: 10px 10px 7px 64px; background-size: 40px; /* border-bottom: 1px solid #000; */ - color: #fff; + color: colors.$white; margin: 0 !important; text-align: left; font-family: 'calibri', Arial, Helvetica, sans-serif; } - .popup .x-popup { - color: #fff; - text-decoration: none; - display: block; - height: 30px; - font-size: 20px; - padding-top: 10px; - float: right; - margin: 0 10px 0 0; - background-size: 22px; - font-family: 'icomoon'; - speak: none; - font-style: normal; - font-weight: normal; - font-variant: normal; - text-transform: none; - line-height: 1; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - } - - .x-popup:before { - content: '\f057'; - } - .inner { width: 45px; - border-right: 1px solid #003366; + border-right: 1px solid colors.$blue900; border-radius: 0 0 0 6px; } .btn-ok, .btn-cancel { - color: #fff; - background: colors.$translatedBlue; + color: colors.$white; + background: colors.$blue500; font-weight: bold; text-decoration: none; padding: 8px 10px; @@ -116,20 +91,20 @@ cursor: pointer; } .btn-ok:hover { - background-color: colors.$translatedBlueHover; + background-color: colors.$blue600; } .btn-ok:active { - background-color: colors.$translatedBlueActive; + background-color: colors.$blue600; } .btn-cancel { - color: colors.$grey1 !important; + color: colors.$grey500 !important; background: white !important; - border: 1px solid colors.$grey1 !important; + border: 1px solid colors.$grey500 !important; } .btn-cancel:hover { cursor: pointer; - background-color: colors.$grey3 !important; + background-color: colors.$grey150 !important; } } diff --git a/public/css/sass/speech2text.scss b/public/css/sass/speech2text.scss index e0b8307ce9..43ca086c9a 100644 --- a/public/css/sass/speech2text.scss +++ b/public/css/sass/speech2text.scss @@ -1,9 +1,10 @@ @use 'commons/mixins'; +@use './commons/colors'; .activeSegmentButton { @include mixins.box-shadow(inset 0 1px 2px rgba(0, 0, 0, 0.1)); - @include mixins.linear-gradient(#eee, top, #eee, #e0e0e0); - border-color: #ccc; + @include mixins.linear-gradient(colors.$grey75, top, colors.$grey75, colors.$grey200); + border-color: colors.$grey200; } .editarea.micActive { @@ -23,7 +24,7 @@ &:hover { svg g { - fill: #000000; + fill: colors.$black; } } @@ -37,7 +38,7 @@ /* @extend .activeSegmentButton; */ svg g { - fill: #fff; + fill: colors.$white; } } @@ -59,12 +60,12 @@ @include mixins.animation-direction(alternate); svg g { - fill: #ffffff; + fill: colors.$white; } } svg g { - fill: #737373; + fill: colors.$grey600; } } diff --git a/public/css/sass/style.scss b/public/css/sass/style.scss index 9cd0465aee..63d27aa615 100644 --- a/public/css/sass/style.scss +++ b/public/css/sass/style.scss @@ -1,4 +1,5 @@ @use 'commons/colors'; +@use 'commons/variables'; body { transition: padding-top 200ms ease-out; -webkit-transition: padding-top 200ms ease-out; @@ -25,11 +26,11 @@ body.incomingMsg header { header .wrapper { width: 100%; - background: #002b5c; + background: colors.$blue900; height: 60px; display: grid; grid-template-columns: 170px auto auto 64px; - padding: 0 24px; + padding: 0 40px 0 15px; align-content: center; box-sizing: border-box; top: 0; @@ -55,124 +56,7 @@ header .wrapper { } .text a { - text-color: #000; -} - -#notifbox { - opacity: 0.9; - text-align: center; - width: 45px; - color: #777; - height: 27px; - padding-top: 12px; - cursor: pointer; -} - -#notifbox.warningbox { - padding-top: 12px !important; -} - -#notifbox a { - display: block; - width: 36px; - height: 36px; - padding: 0; - margin: 0 auto; - text-decoration: none; -} - -#point2seg { - color: #fff; -} - -body.search-open header .header-menu #action-search { - /*background-image: url("../../img/icons/icon-search-active.svg");*/ - opacity: 1; - svg { - circle { - fill: #002b5c; - } - .st1 { - fill: #fff; - } - } -} - -.numbererror, -.qa-total-issues-counter, -.qa-issues-counter, -.qa-glossary-counter, -.qa-conflicts-issues-counter, -.qa-lexiqa-counter { - position: absolute; - color: #fff; - background: #e20001; - margin-left: 20px; - margin-top: -8px; - -moz-border-radius: 10px; - border-radius: 10px; - /*border: 1px solid #fff;*/ - display: block; - font-size: 11px; - padding: 0 4px; - text-align: center; - /*min-width: 8px;*/ - height: 15px; - line-height: 1.5; - box-sizing: content-box; -} - -.numbererror { - border-radius: 25px; - right: -4px; - font-size: 10px; - line-height: 16px; - top: 0; - margin: 0; - padding: 1px 6px; -} - -.numberwarning { - background: #e2be26 !important; -} -.numberinfo { - background: #0bbeec !important; -} - -.numbererror:empty { - display: none; -} - -.action-submenu.notific:before { - font-size: 18px; - color: #3aa94f; - content: ''; - display: none; /* Don't display icon if all ok */ -} - -#point2seg:after { - font-size: 18px; - content: ''; - display: none; /* Don't display icon */ -} - -.notific a { - color: #fff; - text-decoration: none; - height: 16px; - padding: 2px 4px 0 2px !important; - display: block; - margin: -2px 0px 0 2px; - font-size: 12px; - position: absolute; - border-radius: 2px; - -webkit-box-shadow: 0 1px 2px #666; - box-shadow: 0 1px 2px #666; - display: none; -} - -.notific.error { - color: #fff !important; + text-color: colors.$black; } .error a { @@ -183,26 +67,10 @@ body.search-open header .header-menu #action-search { font-size: 16px; } -.error-type a.tooltip { - left: -5px; - top: 10px; -} - -.tag-mismatch { - float: left !important; -} - -.auto-propagation-review { - cursor: pointer; - text-decoration: underline; - color: blue; - color: -webkit-link; -} - .warnings, .text .alternatives { clear: left; - color: #d65959; + color: colors.$red400; float: left; margin-left: -10px; font-size: 14px; @@ -261,19 +129,19 @@ section.opened .warnings { .cattool #quality-report[data-vote='excellent'], .cattool #quality-report[data-vote='verygood'], .cattool #quality-report[data-vote='good'] { - background-color: #3c9423 !important; + background-color: colors.$green700 !important; } .cattool #quality-report[data-vote='poor'] { - background-color: #ffa935 !important; + background-color: colors.$orange600 !important; } .cattool #quality-report[data-vote='acceptable'] { - background-color: #eaba22 !important; + background-color: colors.$orange400 !important; } .cattool #quality-report[data-vote='fail'] { - background-color: #e7504d !important; + background-color: colors.$red400 !important; } .logo { @@ -297,7 +165,7 @@ section.opened .warnings { } .projectbar { - color: #788190; + color: colors.$grey500; display: flex; justify-content: flex-start; padding: 40px 115px 10px 4.5%; @@ -306,7 +174,7 @@ section.opened .warnings { padding-top: 25px; } span.fileFormat { - padding: 10px 15px 9px 47px; + padding: 10px; background-size: 25px !important; line-height: 16px; white-space: nowrap; @@ -322,21 +190,21 @@ section.opened .warnings { max-width: 80%; } .button-notes { - color: #fff !important; + color: colors.$white !important; font-weight: bold; text-decoration: none; padding: 6px 12px; border-radius: 2px; font-size: 16px; - background: colors.$translatedBlue; - background: -moz-linear-gradient(top, colors.$translatedBlue, #119ec4); - background: linear-gradient(top, colors.$translatedBlue, #119ec4); + background: colors.$blue500; + background: -moz-linear-gradient(top, colors.$blue500, colors.$blue500); + background: linear-gradient(top, colors.$blue500, colors.$blue500); user-select: none; cursor: pointer; min-width: 95px; margin-left: 15px; &:hover { - background-color: colors.$translatedBlueHover; + background-color: colors.$blue600; } svg { display: block; @@ -362,7 +230,7 @@ section.opened .warnings { width: 15%; float: left; margin: 0 15px 5px 0 !important; - background: #fff; + background: colors.$white; overflow: hidden; -webkit-border-radius: 10px; -moz-border-radius: 10px; @@ -370,38 +238,38 @@ section.opened .warnings { } .approved-bar { - background-color: colors.$approvedGreen; + background-color: colors.$green800; } .approved-bar-2nd-pass { - background-color: colors.$approved2Green; + background-color: colors.$purple500; } .draft-bar { - background-color: colors.$grey4; + background-color: colors.$grey100; } .rejected-bar { - background-color: #ed1c24; + background-color: colors.$red500; } .translated-bar { - background-color: colors.$translatedBlue; + background-color: colors.$blue500; } .rejected-background { - background-color: #ed1c24; + background-color: colors.$red500; } .approved-backgruond { - background-color: colors.$approvedGreen; + background-color: colors.$green800; } .rejected-foreground { - color: #ed1c24; + color: colors.$red500; } .approved-foreground { - color: colors.$approvedGreen; + color: colors.$green800; } .meter > a { @@ -489,7 +357,7 @@ section.opened .warnings { text-align: center; display: block; font-size: 11px; - color: #b6b8bb; + color: colors.$grey300; text-decoration: none; cursor: default; height: 100%; @@ -504,7 +372,7 @@ section.opened .warnings { .sid .txt { padding: 0px 3px; margin: 2px 0px 0 0px; - background: colors.$grey5; + background: colors.$grey50; display: contents; } @@ -528,10 +396,10 @@ section.editor .txt.segment-add-inBulk { } section.segment-selected-inBulk .body .text { - background: #edf4fd; + background: colors.$blue50; } section.segment-selected-inBulk .body .text:hover { - background: #edf4fd !important; + background: colors.$blue50 !important; } p.split-shortcut { @@ -569,7 +437,7 @@ p.split-shortcut { } section:hover .sid { - color: colors.$grey1; + color: colors.$grey500; } .editor .sid { @@ -623,7 +491,7 @@ section { /*-webkit-transition: all 100ms ease-in;*/ /*transition: all 100ms ease-in;*/ //box-shadow: 0 0 0 #e0e0e0, 0 0 0px rgba(0, 0, 0, 0.12), 0 2px 4px rgba(0, 0, 0, 0.24) !important; - //border: 1px solid $grey4; + //border: 1px solid $grey100; } strong:first-child { @@ -633,121 +501,6 @@ strong:first-child { .download { position: absolute; } - -/*done & draft*/ -.translated, -.approved, -.guesstags { - color: #fff !important; - font-weight: bold; - text-decoration: none; - padding: 8px 18px; - border-radius: 2px; - font-size: 18px; - background: colors.$translatedBlue; - background: -moz-linear-gradient(top, colors.$translatedBlue, #119ec4); - background: linear-gradient(top, colors.$translatedBlue, #119ec4); - text-transform: uppercase; - user-select: none; -} - -.buttons .approved.disabled, -.buttons .next-unapproved.disabled, -.buttons .next-untranslated.disabled, -.buttons .translated.disabled, -.buttons .guesstags.disabled, -.buttons .disabled { - pointer-events: none; - color: #666 !important; - border-color: #666; - background: #efefef; -} - -.approved { - background: colors.$approvedGreen; -} - -article .translated, -.guesstags, -article .draft, -article .approved { - margin: 0 0px 5px 5px; -} - -.buttons { - float: right; - padding: 0; - -webkit-transition: all 100ms ease-in; - -moz-transition: all 100ms ease-in; /*margin: -15px 2% 0 0;*/ - margin: 0; - position: absolute; - right: 0; -} - -.buttons p { - font-size: 11px; - font-weight: normal; - color: #666; - display: none; - position: absolute; - top: calc(50% + 18px); - left: 50%; - transform: translateX(-50%); - width: 200px; -} - -.buttons li:hover p { - display: block; -} - -.translated { - color: #fff !important; -} - -article .translated, -article .approved, -.guesstags { - text-transform: uppercase; -} - -article .translated:hover, -article .next-untranslated:hover, -.guesstags:hover, -article .draft:hover, -article .btn:hover, -article .approved:hover, -article .next-unapproved:hover, -.search .btn:hover { - cursor: pointer; - //-webkit-box-shadow: 0 1px 2px #ccc; - //box-shadow: 0 1px 2px #ccc; - //border: 1px solid #000; -} - -article .translated:active, -.guesstags:active, -article .draft:active, -article .btn:active, -article .approved:active { - -moz-box-shadow: none; - -webkit-box-shadow: none; - box-shadow: none; -} - -.translated:hover, -.next-untranslated:hover, -.guesstags:hover { - background-color: colors.$translatedBlueHover; - //box-shadow: 0 0 0 #e0e0e0, 0 0 2px rgba(0, 0, 0, 0.12), 0 2px 4px rgba(0, 0, 0, 0.24) !important; -} - -.draft:hover { - background: #eee; -} - -.translated:active, -.draft:active, -.guesstags:active, .btn:active, .copysource:active { -moz-box-shadow: none; @@ -756,38 +509,6 @@ article .approved:active { /* border: 1px solid #000*/ } -.next-untranslated, -.next-unapproved { - width: 50px !important; - height: 27px !important; - background: colors.$translatedBlue; - font-weight: bold; - text-decoration: none; - padding: 5px 2px 3px 2px; - border-radius: 2px; - font-size: 18px; - color: #fff !important; - user-select: none; -} - -.approved, -.next-unapproved { - background: colors.$approvedGreen; - color: #fff !important; -} - -.draft { - background: -webkit-gradient( - linear, - left top, - left bottom, - from(#f5f5f5), - to(#d3d4d5) - ); - background: -moz-linear-gradient(top, #f5f5f5, #d3d4d5); - background: linear-gradient(top, #f5f5f5, #d3d4d5); -} - .btn { cursor: pointer; min-height: 26px; @@ -797,10 +518,6 @@ article .approved:active { border-radius: 2px; } -.buttons .btn { - height: 33px; -} - .outersource .copy { display: none; margin-top: 14px; @@ -830,7 +547,7 @@ article .approved:active { .outersource .copy p { visibility: hidden; font-size: 11px; - color: #666; + color: colors.$grey700; margin-top: 46px; margin-left: -4px; } @@ -842,7 +559,7 @@ article .approved:active { article { //margin: 0px auto 100px auto; -moz-border-radius: 2px; - -moz-box-shadow: 0 1px 3px #ccc; + -moz-box-shadow: 0 1px 3px colors.$grey200; position: relative; width: 100%; float: left; @@ -925,9 +642,9 @@ section .body > .text { } body #file section:not(.editor) { - background: colors.$grey3; + background: colors.$grey150; cursor: pointer; - border: 1px solid colors.$grey2; + border: 1px solid colors.$grey300; .body { height: 100%; } @@ -943,7 +660,7 @@ body #file section:not(.editor) { -webkit-box-shadow: none; box-shadow: none; padding: 5px 0 19px 0; - color: #000; + color: colors.$black; } .cl { @@ -955,10 +672,10 @@ body #file section:not(.editor) { //background: #fff; float: left; position: relative; - color: #666; + color: colors.$grey700; -webkit-transition: all 100ms ease-in; transition: all 100ms ease-in; - //border-bottom: 1px solid $grey2; + //border-bottom: 1px solid $grey300; } ul.suggestion-item.graysmall:last-child { @@ -989,15 +706,15 @@ ul.suggestion-item.graysmall:last-child { .segment-footer-tab-more-button { margin-left: auto; margin-right: auto; - background-color: colors.$grey4 !important; - color: colors.$grey6 !important; + background-color: colors.$grey100 !important; + color: colors.$grey700 !important; gap: 0; padding-right: 16px !important; border-bottom-right-radius: 0; border-bottom-left-radius: 0; &:hover { - background-color: colors.$grey9 !important; + background-color: colors.$grey75 !important; } &.segment-footer-tab-more-button-extended-mode { @@ -1014,7 +731,7 @@ ul.suggestion-item.graysmall:last-child { /*submenu*/ .submenu { - background: #fff; + background: colors.$white; text-align: left; width: 100%; } @@ -1029,8 +746,8 @@ ul.suggestion-item.graysmall:last-child { section.loaded .submenu { display: block; - border-bottom-left-radius: 8px; - border-bottom-right-radius: 8px; + border-bottom-left-radius: variables.$border-radius-default; + border-bottom-right-radius: variables.$border-radius-default; overflow: hidden; &:has(.active) { @@ -1047,11 +764,19 @@ section.loaded .submenu { float: left; position: relative; width: auto !important; - background: colors.$grey4; + background: colors.$grey100; z-index: 1; - border-bottom: 1px solid colors.$grey3; + border-bottom: 1px solid colors.$grey150; cursor: pointer; user-select: none; + + &:last-child { + border-top-right-radius: variables.$border-radius-default; + + > a { + border-top-right-radius: variables.$border-radius-default; + } + } } .submenu li.active { @@ -1064,12 +789,12 @@ section.loaded .submenu { -moz-transition: all 100ms ease-in; padding: 5px 20px; display: block; - color: colors.$grey1; + color: colors.$grey500; font-size: 16px; float: left; text-decoration: none; - border-right: 2px solid colors.$grey3; - border-top: 2px solid colors.$grey3; + border-right: 2px solid colors.$grey150; + border-top: 2px solid colors.$grey150; } .submenu .notification:hover { @@ -1077,22 +802,22 @@ section.loaded .submenu { } .submenu a:hover { - background: #f5f5f5; - color: colors.$grey1; + background: colors.$grey50; + color: colors.$grey500; -moz-box-shadow: none; //position: relative; -webkit-box-shadow: none; } .submenu .on { - background: #fff; - color: #000; + background: colors.$white; + color: colors.$black; font-size: 14px; text-shadow: none; } .tab-switcher.loading-tab a { - color: #929292; + color: colors.$grey400; padding-right: 36px; } @@ -1114,14 +839,14 @@ section.loaded .submenu { .icon-close { display: block; height: 15px; - color: colors.$grey1; + color: colors.$grey500; } } .submenu li.active a { //background: #fff !important; outline: none; - color: #000; + color: colors.$black; } .submenu li.modified a { @@ -1132,7 +857,7 @@ section.loaded .submenu { display: none; float: left; width: 100%; - background: #ffffff; + background: colors.$white; } .sub-editor.open { @@ -1155,11 +880,11 @@ section.loaded .submenu { bottom: -24px; right: 0px; border-radius: 0 0 0 2px; - color: #fff; + color: colors.$white; padding: 3px 10px 7px 4px; font-size: 12px; - background: colors.$translatedBlue; - box-shadow: 0px 2px 4px 0px #868686; + background: colors.$blue500; + box-shadow: 0px 2px 4px 0px colors.$grey600; z-index: 2; } @@ -1171,9 +896,9 @@ section.loaded .submenu { .concordances .more { display: inline-block; text-decoration: none; - color: #fff; + color: colors.$white; padding: 0 10px; - background: #999; + background: colors.$grey400; font-size: 14px; border-top-left-radius: 6px; border-top-right-radius: 6px; @@ -1202,7 +927,7 @@ section.loaded .submenu { .footer-message { margin-left: 20px; - background: #ffde33 !important; + background: colors.$orange200 !important; padding: 2px 10px; } @@ -1218,12 +943,12 @@ section.loaded .submenu { .filter { width: 24px; height: 24px; - box-shadow: 0px 0px 1px #aeaeae; + box-shadow: 0px 0px 1px colors.$grey400; display: block; float: right; margin: -5px 10px -2px 0; - border-left: 1px solid #333; - border-right: 1px solid #333; + border-left: 1px solid colors.$grey1300; + border-right: 1px solid colors.$grey1300; -webkit-transition: all 100ms ease-in; -moz-transition: all 100ms ease-in; position: relative; @@ -1231,7 +956,7 @@ section.loaded .submenu { } .search-display .found .warning { - color: #e60000; + color: colors.$red500; } .search .loader { @@ -1245,11 +970,11 @@ section.loaded .submenu { .filtering .filter, .filtering .filter:hover { - background-color: #434345; + background-color: colors.$grey1300; } .filter:hover { - background-color: #636567; + background-color: colors.$grey700; } .checkbox { @@ -1263,7 +988,7 @@ section.loaded .submenu { margin: 4px 10px 3px 0; padding: 2px 20px; height: 28px; - background: #dcdedf; + background: colors.$grey200; cursor: pointer; font-size: 14px; width: 120px; @@ -1279,7 +1004,7 @@ section.loaded .submenu { .editor, .editor .text { - background: #fff; + background: colors.$white; } .loader:not(.ui) { @@ -1330,26 +1055,26 @@ section.editor .loader_on { font-size: 15px; margin-top: 3px; border-radius: 20px; - background: #fff; - color: #aeaeae; + background: colors.$white; + color: colors.$grey400; } .close:hover { background: red; - color: #fff; + color: colors.$white; text-align: center; } section .header .context { display: none; float: left; - color: colors.$grey1; + color: colors.$grey500; text-decoration: none; margin: 3px 0 0 10px; } section .header .context:hover { - color: #000; + color: colors.$black; } .percentuage.visible { @@ -1357,21 +1082,21 @@ section .header .context:hover { } .qa { - background: #ffcc00; - -moz-box-shadow: 0 1px 3px colors.$grey2; - -webkit-box-shadow: 0 1px 3px colors.$grey2; + background: colors.$orange200; + -moz-box-shadow: 0 1px 3px colors.$grey300; + -webkit-box-shadow: 0 1px 3px colors.$grey300; padding: 0 2px; } section .text .warning { - background: #ffcc00; + background: colors.$orange200; padding: 2px 7px; text-align: center; - border: 1px solid #333; + border: 1px solid colors.$grey1300; -moz-border-radius: 2px; border-radius: 2px; - -moz-box-shadow: 0 1px 3px colors.$grey2; - -webkit-box-shadow: 0 1px 3px colors.$grey2; + -moz-box-shadow: 0 1px 3px colors.$grey300; + -webkit-box-shadow: 0 1px 3px colors.$grey300; display: block; position: absolute; bottom: -30px; @@ -1428,7 +1153,7 @@ section.opened { padding: 0; } .revise-lock-editArea-active { - background-color: colors.$grey4; + background-color: colors.$grey100; } } } @@ -1440,7 +1165,7 @@ section.opened { resize: none; margin: 2px 0 0px -11px; padding: 5px; - color: #4d4d4f; + color: colors.$grey700; border: 1px solid transparent; -moz-border-radius: 2px; border-radius: 2px; @@ -1454,11 +1179,11 @@ section.readonly { section.ice-locked:not(.segment-selected) .text { cursor: no-drop !important; - background-color: #f2f4f7 !important; + background-color: colors.$grey50 !important; } body section:not(.editor).ice-locked { - background: #dde0e4 !important; + background: colors.$grey150 !important; } .ice-locked-icon > button { @@ -1468,7 +1193,7 @@ body section:not(.editor).ice-locked { border: 1px solid transparent; border-radius: 2px; cursor: pointer; - color: #aaa; + color: colors.$grey400; position: relative; margin-bottom: 5px; top: 2px; @@ -1485,12 +1210,12 @@ button.unlock-button.unlocked.icon-unlocked3:before { } section:hover .ice-locked-icon > button { - color: #6d6e71; + color: colors.$grey600; } .ice-locked-icon > button:hover { - background-color: #9e9e9e; - border: 1px solid #5f5f5f; + background-color: colors.$grey400; + border: 1px solid colors.$grey700; color: white !important; } @@ -1501,8 +1226,8 @@ body.archived section { section.readonly, body.archived section { - background: #f2f4f7; - color: #a4a6a9; + background: colors.$grey50; + color: colors.$grey400; cursor: not-allowed !important; } section.readonly .status-container a.status:hover, @@ -1517,18 +1242,18 @@ body.archived section .status-container a.status:hover { word-break: normal; line-height: 25px; outline: none; - color: #000; - border: 1px solid #dedede; - box-shadow: inset 0 1px 2px colors.$grey2; - -webkit-box-shadow: inset 0 1px 2px colors.$grey2; + color: colors.$black; + border: 1px solid colors.$grey200; + box-shadow: inset 0 1px 2px colors.$grey300; + -webkit-box-shadow: inset 0 1px 2px colors.$grey300; /*font-variant-ligatures: none;*/ cursor: text; } .editarea:focus { - border: 1px solid #96c8da; - box-shadow: inset 0px 0px 2px 2px #96c8da; - outline-color: #96c8da; + border: 1px solid colors.$grey300; + box-shadow: inset 0px 0px 2px 2px colors.$grey300; + outline-color: colors.$grey300; } .source { @@ -1585,11 +1310,6 @@ body.archived section .status-container a.status:hover { padding-left: 26px !important; } -.buttons { - position: relative; - top: 0px; -} - /*tab rows */ .graysmall li { width: 48%; @@ -1597,7 +1317,7 @@ body.archived section .status-container a.status:hover { margin: 2px 1px 0px 0; padding: 12px 20px 12px 34px; text-align: left; - color: #666; + color: colors.$grey700; list-style: none; font-size: 14px; line-height: 16px; @@ -1658,7 +1378,7 @@ body.archived section .status-container a.status:hover { margin-left: 30px; width: 60%; padding: 3px 0; - border-top: 1px dotted colors.$grey2; + border-top: 1px dotted colors.$grey300; font-style: italic; overflow: hidden; } @@ -1675,7 +1395,6 @@ body.archived section .status-container a.status:hover { } .message li { - background: url(/public/img/bad.png) 22px center no-repeat; padding-left: 40px !important; background-size: 12px 12px; } @@ -1686,12 +1405,12 @@ body.archived section .status-container a.status:hover { .trash:hover { margin-top: -2px; - color: #000; + color: colors.$black; } .trash { transition: all 0.1s linear; - color: colors.$grey1; + color: colors.$grey500; text-decoration: none; -o-transition: all 0.1s linear; -webkit-transition: all 0.1s linear; @@ -1710,7 +1429,7 @@ body.archived section .status-container a.status:hover { position: absolute; font-size: 10px; display: none; - color: #999999; + color: colors.$grey400; } .graysmall:hover .graysmall-message { @@ -1721,7 +1440,7 @@ body.archived section .status-container a.status:hover { display: none; position: absolute; bottom: 0px; - color: colors.$grey1; + color: colors.$grey500; width: 100%; float: left; margin: 0; @@ -1762,7 +1481,7 @@ body.archived section .status-container a.status:hover { } .graysmall:hover { - background: colors.$grey5; + background: colors.$grey50; cursor: default; .tag { opacity: 1; @@ -1770,7 +1489,7 @@ body.archived section .status-container a.status:hover { } .message:hover { - background: #fbfbfb !important; + background: colors.$white !important; cursor: auto; } @@ -1779,7 +1498,7 @@ body.archived section .status-container a.status:hover { } .error-img { - background: #c5351c url(/public/img/warning.png) no-repeat center; + background: colors.$red600 url(/public/img/warning.png) no-repeat center; background-size: 17px; width: 22px; height: 22px; @@ -1792,7 +1511,7 @@ body.archived section .status-container a.status:hover { } .warning-img { - background: #ff9900 url(/public/img/warning.png) no-repeat center; + background: colors.$orange600 url(/public/img/warning.png) no-repeat center; background-size: 17px; width: 22px; height: 22px; @@ -1815,7 +1534,7 @@ body.archived section .status-container a.status:hover { } .engine-error-item.graysmall:hover { - background-color: #fff; + background-color: colors.$white; border-top: unset; } @@ -1835,7 +1554,7 @@ body.archived section .status-container a.status:hover { position: absolute; right: 0; height: 100%; - background: colors.$grey2; + background: colors.$grey300; top: 0; border-bottom: 0; z-index: 0; @@ -1862,20 +1581,20 @@ body.archived section .status-container a.status:hover { } section.status-translated .status { - background-color: colors.$translatedBlue !important; + background-color: colors.$blue500 !important; } section.status-approved .status { - background-color: colors.$approvedGreen !important; + background-color: colors.$green800 !important; } section.status-approved2 .status { - background-color: colors.$approved2Green !important; + background-color: colors.$purple500 !important; } /* section.status-draft .status{background-color:#dddedf !important;} */ section.status-rejected .status { - background-color: colors.$rebuttedRed !important; + background-color: colors.$orange600 !important; } .message-offline-icons { @@ -1885,7 +1604,7 @@ section.status-rejected .status { } section.editor.status-rejected .status { - background-color: colors.$rebuttedRed !important; + background-color: colors.$orange600 !important; } section.modified .status { @@ -1919,42 +1638,42 @@ section.opened.editor .status { } .per-orange { - background: colors.$rebuttedRed !important; - color: #fff !important; + background: colors.$orange600 !important; + color: colors.$white !important; } .per-blue { - background: colors.$translatedBlue !important; - color: #fff !important; + background: colors.$blue500 !important; + color: colors.$white !important; } .per-green { - background: colors.$approvedGreen !important; - color: #fff !important; + background: colors.$green800 !important; + color: colors.$white !important; } .per-yellow { - background: colors.$orangeDefault !important; - color: #333 !important; + background: colors.$orange200 !important; + color: colors.$grey1300 !important; } .per-red { - background: colors.$redDefault !important; - color: #fff !important; + background: colors.$red500 !important; + color: colors.$white !important; } .per-gray { - background: colors.$grey3 !important; - color: #333 !important; + background: colors.$grey150 !important; + color: colors.$grey1300 !important; } .per-red-outline { margin-left: 5px !important; background-color: transparent !important; - color: colors.$redDefault !important; - box-shadow: inset 0px 0px 0px 1px colors.$redDefault; - -moz-box-shadow: inset 0px 0px 0px 1px colors.$redDefault; - -webkit-box-shadow: inset 0px 0px 0px 1px colors.$redDefault; + color: colors.$red500 !important; + box-shadow: inset 0px 0px 0px 1px colors.$red500; + -moz-box-shadow: inset 0px 0px 0px 1px colors.$red500; + -webkit-box-shadow: inset 0px 0px 0px 1px colors.$red500; } .graysmall-details .per-yellow, @@ -1999,7 +1718,6 @@ section.opened.editor .status { } @media screen and (max-width: 1380px) { - /*.buttons{margin:-15px 43px 0 0 !important;}*/ .graysmall li { width: 45.5%; } @@ -2085,13 +1803,6 @@ section.opened.editor .status { /* word-break: break-all */ } - .translated, - .draft, - .approved, - .guesstags { - padding: 8px 6px; - } - .meter { width: 10%; } @@ -2108,10 +1819,6 @@ section.opened.editor .status { width: 43%; } - #notifbox { - width: 45px; - } - .text .source.item, .text .target.item, .white li, @@ -2151,16 +1858,6 @@ section.opened.editor .status { } } -@media screen and (max-width: 1100px) { - #notifbox { - width: 45px; - } - - .cattool #quality-report { - padding: 0 !important; - } -} - /*RTL language*/ .editarea.rtl, .source.rtl, @@ -2182,7 +1879,7 @@ section.ice-locked.rtl-target .target { text-align: right; } -body.archived ul.buttons, +body.archived .buttons, body.archived .footer { display: none !important; } @@ -2193,11 +1890,11 @@ p.percent { } ins.diff { - background: #c3ffc3; + background: colors.$green200; } del.diff { - background: #ffcfcf; + background: colors.$red100; } .editToolbar { @@ -2212,12 +1909,12 @@ del.diff { } .split { - border: 1px solid #5f5f5f; + border: 1px solid colors.$grey700; cursor: pointer !important; font-size: 17px; - background-color: #9e9e9e; + background-color: colors.$grey400; border-radius: 2px; - color: #ffffff; + color: colors.$white; margin-bottom: 0px; top: 2px; padding: 0; @@ -2244,7 +1941,7 @@ del.diff { } .editor.split-action .actions .split { - background: colors.$translatedBlue; + background: colors.$blue500; } section .toolbar { @@ -2406,12 +2103,12 @@ section.editor .toolbar { .addtmx-tr.white-tx .open-popup-addtm-tr { width: 130px; - color: #333; - background: #fff; + color: colors.$grey1300; + background: colors.$white; } .addtmx-tr.white-tx .open-popup-addtm-tr:hover { - background: #ededed; + background: colors.$grey100; } .open-popup-addtm-tr { @@ -2425,22 +2122,22 @@ section.editor .toolbar { } .addtmx-tr:active { - -moz-box-shadow: inset 0 0 1px 1px #888; - -webkit-box-shadow: inset 0 0 1px 1px #888; - box-shadow: inset 0 0 1px 1px #888; + -moz-box-shadow: inset 0 0 1px 1px colors.$grey400; + -webkit-box-shadow: inset 0 0 1px 1px colors.$grey400; + box-shadow: inset 0 0 1px 1px colors.$grey400; } .alternatives .deleted, .suggestion_source .deleted, .suggestion_source del { - background: #ffc7ca; + background: colors.$red100; text-decoration: line-through; } .alternatives .added, .suggestion_source .added, .suggestion_source ins { - background: #b0ffb3; + background: colors.$green300; text-decoration: none; } @@ -2455,15 +2152,15 @@ section.editor .toolbar { width: 100%; padding: 3px 0px 5px 3px; margin: 7px 1.7%; - background: #efefef; + background: colors.$grey75; font-size: 18px; min-height: 70px; outline: 0; text-align: left; border-radius: 2px; line-height: 27px; - color: #000; - border: 1px solid #727272; + color: colors.$black; + border: 1px solid colors.$grey600; word-break: normal !important; cursor: col-resize; float: left; @@ -2472,7 +2169,7 @@ section.editor .toolbar { margin-right: 4px; width: 108px; float: left; - color: #333; + color: colors.$grey1300; } } @@ -2502,14 +2199,14 @@ section.editor .toolbar { } .splitBar .btn-ok:hover { - background: #12b4df; + background: colors.$blue200; } .splitpoint { display: inline-block; width: 8px; height: 26px; - color: #767676; + color: colors.$grey600; cursor: pointer; width: 19px; margin: 0px 5px; @@ -2533,28 +2230,28 @@ section .footer .tab.open { display: block; z-index: 0; position: relative; - border-top: 1px solid colors.$grey3; + border-top: 1px solid colors.$grey150; top: -1px; min-height: 40px; background-color: colors.$white; } section .segment-side-buttons { - color: colors.$grey1; + color: colors.$grey500; } .grey-button { - color: #333; - background: #f6f6f6; + color: colors.$grey1300; + background: colors.$grey50; background: -webkit-gradient( linear, left top, left bottom, - from(#f6f6f6), - to(#e2e3e5) + from(colors.$grey50), + to(colors.$grey100) ); - background: -moz-linear-gradient(top, #f6f6f6, #e2e3e5); - background: linear-gradient(top, #f6f6f6, #e2e3e5); + background: -moz-linear-gradient(top, colors.$grey50, colors.$grey100); + background: linear-gradient(top, colors.$grey50, colors.$grey100); } .edit-distance { @@ -2563,7 +2260,7 @@ section .segment-side-buttons { top: 4px; right: 6px; font-size: 0.8rem; - color: #999; + color: colors.$grey400; } .ui.user.label { @@ -2579,364 +2276,6 @@ section .segment-side-buttons { position: relative; } -.buttons li { - text-align: center; - vertical-align: -webkit-baseline-middle; - display: inline-block; - position: relative; - margin-left: 16px; -} - -/* Header/Footer Restyling */ - -$icon-scale: 30px; - -/* Default */ - -header { - .wrapper { - grid-template-columns: - 208px minmax(0, 48px) minmax(200px, max-content) - auto max-content; /*208px minmax(0,48px) minmax(200px, max-content) auto 120px;*/ - align-items: center; - - .popover-component-container { - margin-left: 15px; - } - } - - .logo-menu { - display: grid; - align-items: center; - - .logo { - margin: 0; - background: url(/public/img/logo_matecat_big_white.svg) 0 0 no-repeat; - width: 190px; - height: 40px; - top: 1px; - left: 6px; - } - } - - .header-menu { - display: grid; - /*grid-template-columns: repeat(9, auto);*/ - grid-auto-flow: column; - grid-template-rows: $icon-scale; - align-items: center; - justify-content: right; - column-gap: 15px; - z-index: 4; - - #previewDropdown[data-download='false'] li.downloadTranslation, - #previewDropdown[data-download='true'] li.previewLink { - display: none; - } - - .draft:hover { - background: transparent; - } - - .action-submenu, - #quality-report { - position: relative; - display: grid; - align-items: center; - grid-template-columns: $icon-scale; - grid-template-rows: $icon-scale; - opacity: 0.8; - - background-repeat: no-repeat; - background-position: center; - margin: 0; - border-radius: 2px; - cursor: pointer; - &.disabled { - opacity: 0.4 !important; - cursor: default !important; - &:hover { - opacity: 0.4 !important; - } - a { - display: none !important; - } - } - &:hover, - &.active { - opacity: 1; - .menu { - visibility: visible; - } - } - - /* Bug fix for Semantic UI Dropdown hover */ - &:hover .dropdown-menu-overlay { - width: 30px; - height: 80px; - } - - .feedback-alert { - position: absolute; - margin: 0; - top: -8px; - padding: 0px 8px; - right: -12px; - background: colors.$orangeDefault; - color: #fff; - font-size: 10px; - text-align: center; - border-radius: 25px; - vertical-align: middle; - line-height: 16px; - height: 17px; - } - - .menu { - position: absolute; - z-index: 1; - width: 200px !important; - left: -85px !important; - margin: 0 0 0 -1px; - background: white; - padding: 12px 8px; - top: 50px !important; - font-size: 16px; - border-radius: 2px; - border: solid 1px #cdd4de; - visibility: hidden; - .item { - padding: 0 !important; - border-radius: 3px; - a, - > span { - display: block; - border-radius: 2px; - padding: 8px !important; - font-size: 16px; - color: #000000; - text-decoration: none; - &:not(.disabled):hover { - background-color: colors.$grey3; - color: colors.$translatedBlue; - } - &.selected { - background-color: transparent !important; - font-weight: normal !important; - } - } - - > span { - display: block; - width: 100%; - } - .disabled { - > span { - color: lightgray; - } - } - } - - .active.item { - background-color: transparent !important; - font-weight: normal !important; - } - } - - .badge { - position: absolute; - margin: 0; - top: 0; - padding: 1px 6px; - right: -4px; - /*background: #e02020;*/ - background: #0bbeec; - color: #fff; - font-size: 10px; - text-align: center; - border-radius: 25px; - vertical-align: middle; - line-height: 16px; - height: 17px; - } - } - #action-download { - background-image: url('/public/img/icons/icon-download.svg'); - background-size: 30px; - &.job-completed { - background-image: url('/public/img/icons/icon-download-complete.svg'); - } - } - #action-QR, - #quality-report-button { - /*background-image: url("../../img/icons/icon-QR-line.svg");*/ - #quality-report { - display: grid; - background: transparent; - border: none !important; - opacity: unset; - } - #quality-report svg { - position: absolute; - } - } - - #quality-report-button { - #quality-report { - svg { - .st0 { - fill: none; - stroke: #fafafa; - } - - .st2 { - fill: #ffffff; - } - } - } - - &[data-revised='true'] { - #quality-report { - &[data-vote='excellent'], - &[data-vote='good'], - &[data-vote='verygood'] { - svg { - .st0 { - fill: #5eb304; - stroke: #5eb304; - } - } - } - &[data-vote='poor'] { - svg { - .st0 { - fill: #ffa935; - stroke: #ffa935; - } - } - } - &[data-vote='acceptable'] { - svg { - .st0 { - fill: #eaba22; - stroke: #eaba22; - } - } - } - - &[data-vote='fail'] { - svg { - .st0 { - fill: #e02020; - stroke: #e02020; - } - } - } - } - } - } - - #notifbox { - width: $icon-scale; - height: $icon-scale; - padding: 0 !important; - text-align: right; - opacity: 0.8; - &:hover { - opacity: 1; - } - a { - position: absolute; - } - } - - #action-comments, - #mbc-history { - width: $icon-scale !important; - height: $icon-scale; - padding: 0 !important; - background-position: center; - - svg { - opacity: 0.8; - &:hover { - opacity: 1; - } - } - &.open svg { - opacity: 1; - } - - .badge { - position: absolute; - margin: 0; - top: 0; - padding: 1px 6px; - right: -4px; - /*background: #e02020;*/ - background: #0bbeec; - color: #fff; - font-size: 10px; - text-align: center; - border-radius: 25px; - vertical-align: middle; - line-height: 16px; - height: 17px; - } - - .mbc-history-balloon-outer { - background: #fff; - margin-top: 5px; - border-radius: 3px; - right: -136px; - z-index: 2; - .mbc-triangle-top { - border-left: 6px solid transparent; - border-right: 6px solid transparent; - border-bottom: 6px solid #ffffff; - bottom: 100%; - left: 50%; - right: auto; - transform: translate(-90%, 0) !important; - position: absolute; - pointer-events: none; - } - - .mbc-thread-wrap-active { - border: none; - } - } - .mbc-history-balloon { - background: #fff; - border-radius: 3px; - } - .mbc-thread-wrap { - border-top: none; - } - } - #action-search { - svg { - circle { - fill: #fff; - } - - .st1 { - fill: #002b5c; - } - } - } - #action-filter { - &.active, - &.open { - opacity: 1; - #filter { - fill: #fff; - } - } - } - } -} - .optionsToolbar { margin-top: 16px; display: flex; diff --git a/public/css/sass/upload-page.scss b/public/css/sass/upload-page.scss index 7f71812e7b..dd2e98fa59 100644 --- a/public/css/sass/upload-page.scss +++ b/public/css/sass/upload-page.scss @@ -1,4 +1,5 @@ -@use "commons/colors"; +@use 'commons/colors'; +@use 'commons/variables'; body { margin: 0; @@ -8,7 +9,6 @@ body { min-height: 100%; } - .translate-box a.tooltip { text-align: center; text-decoration: none !important; @@ -20,11 +20,11 @@ body { .translate-box a.tooltip.gray span, .translate-box a.tooltip.gray { - background: #eee; + background: colors.$grey75; } .translate-box a.tooltip.gray span:after { - border-top: 10px solid #eee; + border-top: 10px solid colors.$grey75; } .translate-box a.tooltip:hover span { @@ -114,10 +114,11 @@ body { } } .translate-box { - float: left; margin: 20px 0 0 0; position: relative; - display: block; + display: flex; + flex-direction: column; + gap: 8px; } .translate-box { @@ -128,18 +129,16 @@ body { .translate-box { h2, .select-with-label__wrapper label { - color: colors.$grey1; - font-size: 18px; + color: colors.$grey1300; + font-size: 16px; font-weight: normal; } .select-with-label__wrapper { + gap: 8px; .select { - font-size: 16px; padding: 9px 46px 9px 12px; - border-radius: 2px; border: 1px solid rgba(34, 36, 38, 0.15); - box-shadow: inset 0 1px 3px #ddd; &:hover { border-color: rgba(34, 36, 38, 0.35); @@ -149,12 +148,12 @@ body { .select--is-focused, .select--is-focused:hover { - border: solid 1px #96c8da; + border: solid 1px colors.$grey300; border-bottom: unset; } .select--is-disabled { - background-color: #f3f3f3; + background-color: colors.$grey75; } .custom-dropdown { @@ -170,7 +169,6 @@ body { .dropdown__search-bar { height: 34px; margin: 0 12px 12px; - border-radius: 4px; border: 1px solid rgba(34, 36, 38, 0.15); background-color: white; @@ -195,7 +193,7 @@ body { } .dropdown__option--is-no-results-found { - color: colors.$grey7; + color: colors.$grey400; } .dropdown__option--is-no-results-found { @@ -206,25 +204,25 @@ body { background-color: unset; color: colors.$black; font-weight: bold; - background-color: colors.$grey5; + background-color: colors.$grey50; } .dropdown__option--is-highlighted-option, .dropdown__option:hover { - background-color: colors.$grey4; + background-color: colors.$grey100; } } .select__dropdown-wrapper { min-width: 350px; - border: solid 1px #96c8da; + border: solid 1px colors.$grey300; border-top: unset; z-index: 3; margin-top: 1px; input:not([type='radio']), textarea { - border: 1px solid colors.$grey2; + border: 1px solid colors.$grey300; border-radius: 4px; padding: 4px 8px; outline: none; @@ -232,7 +230,7 @@ body { line-height: 16px; &:focus, &:focus-visible { - border-color: colors.$linkBlueTransparent; + border-color: colors.$blue300; } } .dropdown__search-bar { @@ -249,7 +247,7 @@ body { cursor: pointer; border: none; background-color: white; - color: #39699a; + color: colors.$blue400; font-size: 14px; font-weight: bold; margin: 0; @@ -262,14 +260,14 @@ body { } &:hover { - background-color: colors.$grey4; + background-color: colors.$grey100; } } } .select-with-icon__wrapper { z-index: 2; - height: 36px; + height: 40px; .select { color: black; } @@ -291,12 +289,9 @@ body { .translate-box.settings { display: flex; align-items: center; - margin: 44px 0 0 0; + margin: 51px 0 0 0; cursor: pointer; } -.translate-box.settings-disabled { - opacity: 0.5; -} .translate-box.qa-box { margin: 32px 0 0 !important; @@ -329,10 +324,9 @@ body { min-width: 992px; max-width: 1600px; position: relative; - padding: 24px; - background: colors.$grey5; - padding-top: 0px; - border-radius: 4px; + padding: 0 24px 24px; + background: colors.$grey50; + border-radius: 16px; } .wrapper-upload h1 { @@ -356,7 +350,7 @@ body { display: grid; align-items: center; justify-content: center; - color: colors.$darkBlue; + color: colors.$blue900; min-width: 992px; /*margin: -3px 0 10px 0;*/ height: 175px; @@ -378,20 +372,15 @@ body { margin: 0px; font-family: Calibri, Arial, Helvetica, sans-serif; .highlight { - color: colors.$translatedBlue; + color: colors.$blue500; } } .wrapper-bottom { - margin: 0 auto; - width: 94%; - min-width: 992px; position: relative; - padding: 12px 0; + padding: 12px 0 0; display: flex; justify-content: space-between; - max-width: 1600px; - align-items: center; } h2 { @@ -409,7 +398,7 @@ h2 { min-width: 200px; font-size: 26px !important; &.disabled { - background: colors.$grey2 !important; + background: colors.$grey300 !important; } .uploadloader { background: url(/public/img/loader.gif) center center no-repeat; @@ -433,7 +422,7 @@ h2 { margin: -2px 0 0 5px; font-size: 13px; font-weight: normal; - color: #999; + color: colors.$grey400; display: none; text-align: center; } @@ -455,10 +444,6 @@ a:hover { font-size: 16px; } -.translate-box label { - margin-left: 5px; -} - body { font-family: Calibri, Arial, Helvetica, sans-serif; } @@ -468,16 +453,16 @@ body { height: 37px; padding: 5px; font-size: 16px; - border: 1px solid #ccc; + border: 1px solid colors.$grey200; margin: 0 0 5px 0; font-family: Calibri, Arial, Helvetica, sans-serif; border-radius: 2px; } a { - color: colors.$linkBlue; + color: colors.$blue700; &:hover { - color: colors.$linkBlueHover; + color: colors.$blue400; } } @@ -485,7 +470,7 @@ a { float: left; font-weight: bold; font-size: 16px; - color: colors.$grey1; + color: colors.$grey500; margin: 0px; .supported-file-formats { cursor: pointer; @@ -495,7 +480,7 @@ a { .btn { height: 44px; display: block; - border: 1px solid #848689; + border: 1px solid colors.$grey500; text-decoration: none; -moz-border-radius: 2px; border-radius: 2px; @@ -508,7 +493,7 @@ a { -moz-box-shadow: none; -webkit-box-shadow: none; border: none; - background: colors.$grey2; + background: colors.$grey300; box-shadow: none !important; } @@ -537,7 +522,7 @@ a { .popup h3 { font-size: 16px; margin: 10px 0 5px 0; - color: #333; + color: colors.$grey1300; } .popup .header { @@ -545,12 +530,12 @@ a { height: 20px; float: left; text-align: left; - background: #efefef; - border-bottom: 1px solid #ccc; + background: colors.$grey75; + border-bottom: 1px solid colors.$grey200; margin-bottom: 5px; - -webkit-box-shadow: inset 0 1px 1px 1px #f4f7f9; - box-shadow: inset 0 1px 1px 1px #f4f7f9; - color: #333; + -webkit-box-shadow: inset 0 1px 1px 1px colors.$grey50; + box-shadow: inset 0 1px 1px 1px colors.$grey50; + color: colors.$grey1300; font-size: 22px; font-weight: bold; padding: 5px 2.5% 10px 1.3%; @@ -570,7 +555,6 @@ a { } .close { - background: url(/public/img/x.png) center 1px no-repeat; width: 22px; height: 20px; display: block; @@ -579,21 +563,16 @@ a { top: 0; } -.close:hover, -.close:focus { - background: url(/public/img/x.png) center -30px no-repeat; -} - .popup .header input { float: right; margin: 1px 0px 0px 15px !important; - background: colors.$translatedBlue; + background: colors.$blue500; font-weight: bold; float: right; font-size: 14px; cursor: pointer; - color: #333; - border: 1px solid #ccc !important; + color: colors.$grey1300; + border: 1px solid colors.$grey200 !important; border-radius: 2px; border-radius: 2px; padding: 3px 12px !important; @@ -605,8 +584,8 @@ a { from(rgb(245, 245, 245)), to(rgb(211, 212, 213)) ); - background: -moz-linear-gradient(top, colors.$translatedBlue, #119ec4); - background: linear-gradient(top, colors.$translatedBlue, #119ec4); + background: -moz-linear-gradient(top, colors.$blue500, colors.$blue500); + background: linear-gradient(top, colors.$blue500, colors.$blue500); } .translate-box h2 span.extra { @@ -619,39 +598,28 @@ a { display: flex; flex-direction: row; height: calc(100% - 50px); - padding: 12px; + padding: 24px; gap: 8px; justify-content: space-between; overflow: auto; - h3 { - padding: 0 30px; - background-color: #efefef; - text-align: center; - } - - span { - padding: 10px 0px 10px 40px; - margin: 5px 0 0 0; - width: 100%; - height: 35px; - float: left; - background-size: 25px !important; + h4 { + padding: 0 24px; + background-color: colors.$grey75; } .format-box { float: none; flex: 1 1 auto; max-width: 300px; .file-list { - float: left; - margin: 0 auto; - float: none; - overflow: hidden; + display: grid; + align-items: center; + grid-template-columns: 1fr 1fr; + gap: 8px; + padding: 16px; > div { - width: 135px; - margin: 0; - padding: 0 5px; - float: left; - text-align: left; + display: flex; + gap: 8px; + padding: 5px; } } } @@ -679,7 +647,8 @@ ul.test li { height: 18px; margin: 52px 14px 0 5px; font-size: 20px; - color: #ccc; + color: colors.$grey200; + cursor: pointer; } #swaplang span { @@ -687,7 +656,7 @@ ul.test li { } #swaplang:hover { - color: #ddd; + color: colors.$grey200; } .name { @@ -726,25 +695,25 @@ header .nav-bar .dropdown.select-org span.text { } .translate-box input:focus { - border-color: #85b7d9; - background: #ffffff; + border-color: colors.$blue300; + background: colors.$white; color: rgba(0, 0, 0, 0.8); outline: none; } select:focus { - border-color: #85b7d9; - background: #ffffff; + border-color: colors.$blue300; + background: colors.$white; color: rgba(0, 0, 0, 0.8); outline: none; } .ui.selection.dropdown { - box-shadow: inset 0 1px 3px #ddd; + box-shadow: inset 0 1px 3px colors.$grey200; } .ui.input input { - box-shadow: inset 0 1px 3px #ddd; + box-shadow: inset 0 1px 3px colors.$grey200; } /* Header restyling */ @@ -760,7 +729,7 @@ select:focus { align-items: center; justify-content: center; padding: 80px 20px; - color: #002b5a; + color: colors.$blue900; div.buttons { padding-top: 20px; } @@ -807,7 +776,7 @@ select:focus { .project-template-select-unsaved { .select { - color: colors.$translatedBlue !important; + color: colors.$blue500 !important; } } @@ -867,7 +836,7 @@ select:focus { .project-template-select-unsaved { .select { - color: colors.$translatedBlue !important; + color: colors.$blue500 !important; } } @@ -875,8 +844,9 @@ select:focus { position: absolute; z-index: 2; width: 100%; - height: 36px; - top: 24px; + height: 40px; + border-radius: variables.$border-radius-default; + top: 32px; background-color: rgba(255, 255, 255, 0.9); .project-template-select-loading-icon { @@ -903,20 +873,19 @@ select:focus { position: absolute; bottom: 0; } - } .error-message, .warning-message { - background: #d65757; - color: #fff; + background: colors.$red400; + color: colors.$white; padding: 10px 0 10px 16px; margin: 10px 0; font-weight: bold; width: 100%; -moz-border-radius: 2px; border-radius: 2px; - border: 1px solid #c45f5f; + border: 1px solid colors.$orange500; display: flex; .icon { float: left; @@ -931,12 +900,12 @@ select:focus { } .error-message { a { - color: #fff; + color: colors.$white; } } .warning-message { background: rgba(255, 250, 139, 0.38) !important; - border-color: #6d6e71; - color: #000; -} \ No newline at end of file + border-color: colors.$grey600; + color: colors.$black; +} diff --git a/public/css/sass/vendor_mc/semantic/_semantic_overrides.scss b/public/css/sass/vendor_mc/semantic/_semantic_overrides.scss index 537030c2f9..e2c517a662 100644 --- a/public/css/sass/vendor_mc/semantic/_semantic_overrides.scss +++ b/public/css/sass/vendor_mc/semantic/_semantic_overrides.scss @@ -15,53 +15,53 @@ .ui.blue.buttons .button, .ui.blue.button { - background-color: colors.$translatedBlue; + background-color: colors.$blue500; } .ui.blue.buttons .button:hover, .ui.blue.button:hover { - background-color: colors.$translatedBlueHover; + background-color: colors.$blue600; } /* Basic */ .ui.basic.blue.buttons .button, .ui.basic.blue.button { - box-shadow: 0px 0px 0px 1px colors.$translatedBlue inset !important; - color: colors.$translatedBlue !important; + box-shadow: 0px 0px 0px 1px colors.$blue500 inset !important; + color: colors.$blue500 !important; } .ui.basic.blue.buttons .button:hover, .ui.basic.blue.button:hover { - color: colors.$translatedBlueHover !important; + color: colors.$blue600 !important; } .ui.basic.blue.buttons .button:focus, .ui.basic.blue.button:focus { - color: colors.$translatedBlueHover !important; + color: colors.$blue600 !important; } /*--- Green ---*/ .ui.green.buttons .button, .ui.green.button { - background-color: colors.$greenDefault; + background-color: colors.$green500; transition: 0.3s ease; } .ui.green.buttons .button:hover, .ui.green.button:hover { - background-color: colors.$greenDefaultHover; + background-color: colors.$green700; //box-shadow: 0 0 0 #e0e0e0, 0 0 2px rgba(0, 0, 0, 0.12), 0 2px 4px rgba(0, 0, 0, 0.24) !important; } .ui.green.buttons .button:focus, .ui.green.button:focus { - background-color: colors.$greenDefaultHover; + background-color: colors.$green700; box-shadow: none !important; } .ui.green.buttons .button:active, .ui.green.button:active { - background-color: colors.$greenDefaultHover; + background-color: colors.$green700; box-shadow: none !important; transition: none !important; } @@ -77,24 +77,24 @@ .ui.red.buttons .button, .ui.red.button { - background-color: colors.$redDefault; + background-color: colors.$red500; } .ui.red.buttons .button:hover, .ui.red.button:hover { - background-color: colors.$redDefaultHover; + background-color: colors.$red600; //box-shadow: 0 0 0 #e0e0e0, 0 0 2px rgba(0, 0, 0, 0.12), 0 2px 4px rgba(0, 0, 0, 0.24) !important; } .ui.red.buttons .button:focus, .ui.red.button:focus { - background-color: colors.$redDefaultHover; + background-color: colors.$red600; box-shadow: none !important; } .ui.red.buttons .button:active, .ui.red.button:active { - background-color: colors.$redDefaultHover; + background-color: colors.$red600; box-shadow: none !important; } @@ -102,7 +102,7 @@ .ui.red.buttons .active.button:active, .ui.red.active.button, .ui.red.button .active.button:active { - background-color: colors.$redDefaultHover; + background-color: colors.$red600; box-shadow: none !important; } @@ -119,26 +119,26 @@ } .ui.primary.buttons .button, .ui.primary.button { - background-color: colors.$translatedBlue; + background-color: colors.$blue500; transition: 0.3s ease; align-items: center; } .ui.primary.buttons .button:hover, .ui.primary.button:hover { - background-color: colors.$translatedBlueHover; + background-color: colors.$blue600; //box-shadow: 0 0 0 #e0e0e0, 0 0 2px rgba(0, 0, 0, 0.12), 0 2px 4px rgba(0, 0, 0, 0.24) !important; } .ui.primary.buttons .button:focus, .ui.primary.button:focus { - background-color: colors.$translatedBlueActive; + background-color: colors.$blue600; box-shadow: none !important; } .ui.primary.buttons .button:active, .ui.primary.button:active { - background-color: colors.$translatedBlueActive; + background-color: colors.$blue600; box-shadow: none !important; transition: none; } @@ -154,18 +154,18 @@ .ui.basic.primary.buttons .button, .ui.basic.primary.button { - box-shadow: 0px 0px 0px 1px colors.$translatedBlue inset !important; - color: colors.$translatedBlue !important; + box-shadow: 0px 0px 0px 1px colors.$blue500 inset !important; + color: colors.$blue500 !important; } .ui.basic.primary.buttons .button:hover, .ui.basic.primary.button:hover { - color: colors.$translatedBlueHover !important; + color: colors.$blue600 !important; } .ui.basic.primary.buttons .button:focus, .ui.basic.primary.button:focus { - color: colors.$translatedBlueActive !important; + color: colors.$blue600 !important; } /*--------------- @@ -204,7 +204,7 @@ i.flag.burma:before { /* Blue */ i.blue.icon { - color: colors.$translatedBlue !important; + color: colors.$blue500 !important; } i.inverted.blue.icon { @@ -213,7 +213,7 @@ i.inverted.blue.icon { i.inverted.bordered.blue.icon, i.inverted.circular.blue.icon { - background-color: colors.$translatedBlue !important; + background-color: colors.$blue500 !important; color: #ffffff !important; } @@ -221,16 +221,16 @@ i.inverted.circular.blue.icon { .ui.blue.labels .label, .ui.blue.label { - background-color: colors.$translatedBlue !important; - border-color: colors.$translatedBlue !important; + background-color: colors.$blue500 !important; + border-color: colors.$blue500 !important; } /* Link */ .ui.blue.labels .label:hover, a.ui.blue.label:hover { - background-color: colors.$translatedBlueHover !important; - border-color: colors.$translatedBlueHover !important; + background-color: colors.$blue600 !important; + border-color: colors.$blue600 !important; } /* Ribbon */ @@ -238,14 +238,14 @@ a.ui.blue.label:hover { /* Basic */ .ui.basic.blue.label { - color: colors.$translatedBlue !important; - border-color: colors.$translatedBlue !important; + color: colors.$blue500 !important; + border-color: colors.$blue500 !important; } .ui.basic.blue.labels a.label:hover, a.ui.basic.blue.label:hover { - color: colors.$translatedBlueHover !important; - border-color: colors.$translatedBlueHover !important; + color: colors.$blue600 !important; + border-color: colors.$blue600 !important; } /* Colors */ @@ -253,11 +253,11 @@ a.ui.basic.blue.label:hover { /* Blue */ .ui.blue.segment:not(.inverted) { - border-top: 2px solid colors.$translatedBlue; + border-top: 2px solid colors.$blue500; } .ui.inverted.blue.segment { - background-color: colors.$translatedBlue !important; + background-color: colors.$blue500 !important; } /*---------------------- @@ -267,7 +267,7 @@ a.ui.basic.blue.label:hover { .ui.grid > .blue.row, .ui.grid > .blue.column, .ui.grid > .row > .blue.column { - background-color: colors.$translatedBlue !important; + background-color: colors.$blue500 !important; } /*-------------- @@ -277,8 +277,8 @@ a.ui.basic.blue.label:hover { /*--- Standard Colors ---*/ .ui.menu .blue.active.item, .ui.blue.menu .active.item { - border-color: colors.$translatedBlue !important; - color: colors.$translatedBlue !important; + border-color: colors.$blue500 !important; + color: colors.$blue500 !important; } /*-------------- Inverted @@ -294,14 +294,14 @@ a.ui.basic.blue.label:hover { .ui.inverted.menu .blue.active.item, .ui.inverted.blue.menu { - background-color: colors.$translatedBlue; + background-color: colors.$blue500; } /* Colors Message */ .ui.blue.message { - color: colors.$translatedBlue; - box-shadow: 0px 0px 0px 1px colors.$translatedBlue inset, + color: colors.$blue500; + box-shadow: 0px 0px 0px 1px colors.$blue500 inset, 0px 0px 0px 0px rgba(0, 0, 0, 0); } @@ -314,11 +314,11 @@ a.ui.basic.blue.label:hover { /* Blue */ .ui.blue.table { - border-top: 0.2em solid colors.$translatedBlue; + border-top: 0.2em solid colors.$blue500; } .ui.inverted.blue.table { - background-color: colors.$translatedBlue !important; + background-color: colors.$blue500 !important; } /* Blue */ @@ -326,19 +326,19 @@ a.ui.basic.blue.label:hover { .ui.blue.cards > .card, .ui.cards > .blue.card, .ui.blue.card { - box-shadow: 0px 0px 0px 1px #d4d4d5, 0px 2px 0px 0px colors.$translatedBlue, + box-shadow: 0px 0px 0px 1px #d4d4d5, 0px 2px 0px 0px colors.$blue500, 0px 1px 3px 0px #d4d4d5; } .ui.blue.statistics .statistic > .value, .ui.statistics .blue.statistic > .value, .ui.blue.statistic > .value { - color: colors.$translatedBlue; + color: colors.$blue500; } .ui.toggle.checkbox input:checked ~ .box:before, .ui.toggle.checkbox input:checked ~ label:before { - background-color: colors.$translatedBlue !important; + background-color: colors.$blue500 !important; } .ui.scrolling.dropdown .menu .item.item.item, @@ -358,7 +358,7 @@ a.ui.basic.blue.label:hover { /* Blue */ .ui.blue.progress .bar { - background-color: colors.$translatedBlue; + background-color: colors.$blue500; } /********************************************/ diff --git a/public/css/sass/vendor_mc/semantic/matecat_semantic.scss b/public/css/sass/vendor_mc/semantic/matecat_semantic.scss index b607bca33d..2e3f423eb9 100644 --- a/public/css/sass/vendor_mc/semantic/matecat_semantic.scss +++ b/public/css/sass/vendor_mc/semantic/matecat_semantic.scss @@ -17,11 +17,11 @@ } a { - color: colors.$linkBlue; + color: colors.$blue700; &:hover { - color: colors.$linkBlueHover; + color: colors.$blue400; } &:active { - color: colors.$linkBlueActive; + color: colors.$blue400; } } diff --git a/public/img/arrow-menucolor-down.png b/public/img/arrow-menucolor-down.png deleted file mode 100644 index 8f65351d67..0000000000 Binary files a/public/img/arrow-menucolor-down.png and /dev/null differ diff --git a/public/img/arrow-menucolor.png b/public/img/arrow-menucolor.png deleted file mode 100644 index eafffb8d87..0000000000 Binary files a/public/img/arrow-menucolor.png and /dev/null differ diff --git a/public/img/asc.gif b/public/img/asc.gif deleted file mode 100644 index 74157867f2..0000000000 Binary files a/public/img/asc.gif and /dev/null differ diff --git a/public/img/bad.png b/public/img/bad.png deleted file mode 100644 index e0ef12a968..0000000000 Binary files a/public/img/bad.png and /dev/null differ diff --git a/public/img/bg.gif b/public/img/bg.gif deleted file mode 100644 index fac668fcf4..0000000000 Binary files a/public/img/bg.gif and /dev/null differ diff --git a/public/img/btn_gg_sprite.png b/public/img/btn_gg_sprite.png deleted file mode 100644 index 34dfd875d3..0000000000 Binary files a/public/img/btn_gg_sprite.png and /dev/null differ diff --git a/public/img/desc.gif b/public/img/desc.gif deleted file mode 100644 index 3b30b3c58e..0000000000 Binary files a/public/img/desc.gif and /dev/null differ diff --git a/public/img/dot.png b/public/img/dot.png deleted file mode 100644 index b83855993d..0000000000 Binary files a/public/img/dot.png and /dev/null differ diff --git a/public/img/fbimg.png b/public/img/fbimg.png deleted file mode 100644 index 5549212a38..0000000000 Binary files a/public/img/fbimg.png and /dev/null differ diff --git a/public/img/hard-return.png b/public/img/hard-return.png deleted file mode 100644 index 1c6b2ae518..0000000000 Binary files a/public/img/hard-return.png and /dev/null differ diff --git a/public/img/highlighter_icon.png b/public/img/highlighter_icon.png deleted file mode 100644 index 9ba7d79828..0000000000 Binary files a/public/img/highlighter_icon.png and /dev/null differ diff --git a/public/img/icons/AlertIcon.js b/public/img/icons/AlertIcon.js index ac399762aa..202bfea103 100644 --- a/public/img/icons/AlertIcon.js +++ b/public/img/icons/AlertIcon.js @@ -4,11 +4,11 @@ import PropTypes from 'prop-types' const AlertIcon = ({size = 18}) => { return ( { + return ( + + + + ) +} + +AlertIconFull.propTypes = { + size: PropTypes.number, +} + +export default AlertIconFull diff --git a/public/img/icons/ChangePassword.js b/public/img/icons/ChangePassword.js index e257ab75ce..3b67662d4d 100644 --- a/public/img/icons/ChangePassword.js +++ b/public/img/icons/ChangePassword.js @@ -4,7 +4,7 @@ import PropTypes from 'prop-types' const ChangePassword = ({size = 24}) => { return ( - + diff --git a/public/img/icons/CheckCircleBroken.js b/public/img/icons/CheckCircleBroken.js new file mode 100644 index 0000000000..86b0abf51f --- /dev/null +++ b/public/img/icons/CheckCircleBroken.js @@ -0,0 +1,21 @@ +import React from 'react' +import PropTypes from 'prop-types' + +const CheckCircleBroken = ({size = 24}) => { + return ( + + + + ) +} + +CheckCircleBroken.propTypes = { + size: PropTypes.number, +} + +export default CheckCircleBroken diff --git a/public/img/icons/ChevronDown.js b/public/img/icons/ChevronDown.js index c3eaef6183..d6bab5eaeb 100644 --- a/public/img/icons/ChevronDown.js +++ b/public/img/icons/ChevronDown.js @@ -3,13 +3,18 @@ import PropTypes from 'prop-types' const ChevronDown = ({size = 14}) => { return ( - + ) diff --git a/public/img/icons/ChevronLeft.js b/public/img/icons/ChevronLeft.js new file mode 100644 index 0000000000..7b273c9036 --- /dev/null +++ b/public/img/icons/ChevronLeft.js @@ -0,0 +1,21 @@ +import React from 'react' +import PropTypes from 'prop-types' + +const ChevronLeft = ({size = 24}) => { + return ( + + + + ) +} + +ChevronLeft.propTypes = { + size: PropTypes.number, +} + +export default ChevronLeft diff --git a/public/img/icons/ChevronUp.js b/public/img/icons/ChevronUp.js new file mode 100644 index 0000000000..7702e78d9e --- /dev/null +++ b/public/img/icons/ChevronUp.js @@ -0,0 +1,27 @@ +import React from 'react' +import PropTypes from 'prop-types' + +const ChevronUp = ({size = 14}) => { + return ( + + + + ) +} + +ChevronUp.propTypes = { + size: PropTypes.number, +} + +export default ChevronUp diff --git a/public/img/icons/CommentsIcon.js b/public/img/icons/CommentsIcon.js index 0b8fc0254f..53feda2184 100644 --- a/public/img/icons/CommentsIcon.js +++ b/public/img/icons/CommentsIcon.js @@ -3,13 +3,7 @@ import PropTypes from 'prop-types' const CommentsIcon = ({size = 18}) => { return ( - + { + return ( + + + + ) +} + +CommentsIconFilled.propTypes = { + size: PropTypes.number, +} + +export default CommentsIconFilled diff --git a/public/img/icons/CommentsSquareIcon.js b/public/img/icons/CommentsSquareIcon.js new file mode 100644 index 0000000000..ebd889df34 --- /dev/null +++ b/public/img/icons/CommentsSquareIcon.js @@ -0,0 +1,27 @@ +import React from 'react' +import PropTypes from 'prop-types' + +const CommentsSquareIcon = ({size = 18}) => { + return ( + + + + ) +} + +CommentsSquareIcon.propTypes = { + size: PropTypes.number, +} + +export default CommentsSquareIcon diff --git a/public/img/icons/CommentsSquareIconFilled.js b/public/img/icons/CommentsSquareIconFilled.js new file mode 100644 index 0000000000..8db36ec1e3 --- /dev/null +++ b/public/img/icons/CommentsSquareIconFilled.js @@ -0,0 +1,27 @@ +import React from 'react' +import PropTypes from 'prop-types' + +const CommentsSquareIcon = ({size = 18}) => { + return ( + + + + ) +} + +CommentsSquareIcon.propTypes = { + size: PropTypes.number, +} + +export default CommentsSquareIcon diff --git a/public/img/icons/CopyIcon.js b/public/img/icons/CopyIcon.js new file mode 100644 index 0000000000..236d55a7a4 --- /dev/null +++ b/public/img/icons/CopyIcon.js @@ -0,0 +1,27 @@ +import React from 'react' +import PropTypes from 'prop-types' + +const CopyIcon = ({size = 24}) => { + return ( + + + + ) +} + +CopyIcon.propTypes = { + size: PropTypes.number, +} + +export default CopyIcon diff --git a/public/img/icons/FileAttachment.js b/public/img/icons/FileAttachment.js new file mode 100644 index 0000000000..ea3ca004d0 --- /dev/null +++ b/public/img/icons/FileAttachment.js @@ -0,0 +1,27 @@ +import React from 'react' +import PropTypes from 'prop-types' + +const FileAttachment = ({size = 24}) => { + return ( + + + + ) +} + +FileAttachment.propTypes = { + size: PropTypes.number, +} + +export default FileAttachment diff --git a/public/img/icons/FileTypeCode.js b/public/img/icons/FileTypeCode.js new file mode 100644 index 0000000000..7218a14086 --- /dev/null +++ b/public/img/icons/FileTypeCode.js @@ -0,0 +1,41 @@ +import React from 'react' +import PropTypes from 'prop-types' + +const FileTypeCode = ({size = 24}) => { + return ( + + + + + + + + ) +} + +FileTypeCode.propTypes = { + size: PropTypes.number, +} + +export default FileTypeCode diff --git a/public/img/icons/FileTypeFile.js b/public/img/icons/FileTypeFile.js new file mode 100644 index 0000000000..3b782d5892 --- /dev/null +++ b/public/img/icons/FileTypeFile.js @@ -0,0 +1,41 @@ +import React from 'react' +import PropTypes from 'prop-types' + +const FileTypeFile = ({size = 24}) => { + return ( + + + + + + + + ) +} + +FileTypeFile.propTypes = { + size: PropTypes.number, +} + +export default FileTypeFile diff --git a/public/img/icons/FileTypeFolder.js b/public/img/icons/FileTypeFolder.js new file mode 100644 index 0000000000..704a4cc727 --- /dev/null +++ b/public/img/icons/FileTypeFolder.js @@ -0,0 +1,29 @@ +import React from 'react' +import PropTypes from 'prop-types' + +const FileTypeFolder = ({size = 24}) => { + return ( + + + + + ) +} + +FileTypeFolder.propTypes = { + size: PropTypes.number, +} + +export default FileTypeFolder diff --git a/public/img/icons/FileTypeHtml.js b/public/img/icons/FileTypeHtml.js new file mode 100644 index 0000000000..b889c7cb8e --- /dev/null +++ b/public/img/icons/FileTypeHtml.js @@ -0,0 +1,36 @@ +import React from 'react' +import PropTypes from 'prop-types' + +const FileTypeHtml = ({size = 24}) => { + return ( + + + + + + ) +} + +FileTypeHtml.propTypes = { + size: PropTypes.number, +} + +export default FileTypeHtml diff --git a/public/img/icons/FileTypeImage.js b/public/img/icons/FileTypeImage.js new file mode 100644 index 0000000000..5a39e040eb --- /dev/null +++ b/public/img/icons/FileTypeImage.js @@ -0,0 +1,35 @@ +import React from 'react' +import PropTypes from 'prop-types' + +const FileTypeImage = ({size = 24}) => { + return ( + + + + + + ) +} + +FileTypeImage.propTypes = { + size: PropTypes.number, +} + +export default FileTypeImage diff --git a/public/img/icons/FileTypeLink.js b/public/img/icons/FileTypeLink.js new file mode 100644 index 0000000000..2e84be53b8 --- /dev/null +++ b/public/img/icons/FileTypeLink.js @@ -0,0 +1,33 @@ +import React from 'react' +import PropTypes from 'prop-types' + +const FileTypeLink = ({size = 24}) => { + return ( + + + + + + ) +} + +FileTypeLink.propTypes = { + size: PropTypes.number, +} + +export default FileTypeLink diff --git a/public/img/icons/FileTypePdf.js b/public/img/icons/FileTypePdf.js new file mode 100644 index 0000000000..0fc4ba0389 --- /dev/null +++ b/public/img/icons/FileTypePdf.js @@ -0,0 +1,41 @@ +import React from 'react' +import PropTypes from 'prop-types' + +const FileTypePdf = ({size = 24}) => { + return ( + + + + + + + + ) +} + +FileTypePdf.propTypes = { + size: PropTypes.number, +} + +export default FileTypePdf diff --git a/public/img/icons/FileTypePresentation.js b/public/img/icons/FileTypePresentation.js new file mode 100644 index 0000000000..2fb6cca04d --- /dev/null +++ b/public/img/icons/FileTypePresentation.js @@ -0,0 +1,33 @@ +import React from 'react' +import PropTypes from 'prop-types' + +const FileTypePresentation = ({size = 24}) => { + return ( + + + + + + ) +} + +FileTypePresentation.propTypes = { + size: PropTypes.number, +} + +export default FileTypePresentation diff --git a/public/img/icons/FileTypePub.js b/public/img/icons/FileTypePub.js new file mode 100644 index 0000000000..191241199d --- /dev/null +++ b/public/img/icons/FileTypePub.js @@ -0,0 +1,33 @@ +import React from 'react' +import PropTypes from 'prop-types' + +const FileTypePub = ({size = 24}) => { + return ( + + + + + + ) +} + +FileTypePub.propTypes = { + size: PropTypes.number, +} + +export default FileTypePub diff --git a/public/img/icons/FileTypeSpreadsheet.js b/public/img/icons/FileTypeSpreadsheet.js new file mode 100644 index 0000000000..232f59dd84 --- /dev/null +++ b/public/img/icons/FileTypeSpreadsheet.js @@ -0,0 +1,65 @@ +import React from 'react' +import PropTypes from 'prop-types' + +const FileTypeSpreadsheet = ({size = 24}) => { + return ( + + + + + + + + + + + + + + ) +} + +FileTypeSpreadsheet.propTypes = { + size: PropTypes.number, +} + +export default FileTypeSpreadsheet diff --git a/public/img/icons/FileTypeSub.js b/public/img/icons/FileTypeSub.js new file mode 100644 index 0000000000..871ecd6e0d --- /dev/null +++ b/public/img/icons/FileTypeSub.js @@ -0,0 +1,33 @@ +import React from 'react' +import PropTypes from 'prop-types' + +const FileTypeSub = ({size = 24}) => { + return ( + + + + + + ) +} + +FileTypeSub.propTypes = { + size: PropTypes.number, +} + +export default FileTypeSub diff --git a/public/img/icons/FileTypeText.js b/public/img/icons/FileTypeText.js new file mode 100644 index 0000000000..7971c525cd --- /dev/null +++ b/public/img/icons/FileTypeText.js @@ -0,0 +1,37 @@ +import React from 'react' +import PropTypes from 'prop-types' + +const FileTypeText = ({size = 24}) => { + return ( + + + + + + + ) +} + +FileTypeText.propTypes = { + size: PropTypes.number, +} + +export default FileTypeText diff --git a/public/img/icons/FileTypeXliff.js b/public/img/icons/FileTypeXliff.js new file mode 100644 index 0000000000..a9f628b284 --- /dev/null +++ b/public/img/icons/FileTypeXliff.js @@ -0,0 +1,33 @@ +import React from 'react' +import PropTypes from 'prop-types' + +const FileTypeXliff = ({size = 24}) => { + return ( + + + + + + ) +} + +FileTypeXliff.propTypes = { + size: PropTypes.number, +} + +export default FileTypeXliff diff --git a/public/img/icons/FileTypeXls.js b/public/img/icons/FileTypeXls.js new file mode 100644 index 0000000000..33ae83254e --- /dev/null +++ b/public/img/icons/FileTypeXls.js @@ -0,0 +1,35 @@ +import React from 'react' +import PropTypes from 'prop-types' + +const FileTypeXls = ({size = 24}) => { + return ( + + + + + + ) +} + +FileTypeXls.propTypes = { + size: PropTypes.number, +} + +export default FileTypeXls diff --git a/public/img/icons/FileTypeZip.js b/public/img/icons/FileTypeZip.js new file mode 100644 index 0000000000..855d655399 --- /dev/null +++ b/public/img/icons/FileTypeZip.js @@ -0,0 +1,37 @@ +import React from 'react' +import PropTypes from 'prop-types' + +const FileTypeZip = ({size = 24}) => { + return ( + + + + + + + + + + + + + ) +} + +FileTypeZip.propTypes = { + size: PropTypes.number, +} + +export default FileTypeZip diff --git a/public/img/icons/Files.js b/public/img/icons/Files.js new file mode 100644 index 0000000000..b9acb5cdf9 --- /dev/null +++ b/public/img/icons/Files.js @@ -0,0 +1,31 @@ +import React from 'react' +import PropTypes from 'prop-types' + +const Files = ({size = 24}) => { + return ( + + + + + ) +} + +Files.propTypes = { + size: PropTypes.number, +} + +export default Files diff --git a/public/img/icons/FilterFilledIcon.js b/public/img/icons/FilterFilledIcon.js new file mode 100644 index 0000000000..4eaba14584 --- /dev/null +++ b/public/img/icons/FilterFilledIcon.js @@ -0,0 +1,27 @@ +import React from 'react' +import PropTypes from 'prop-types' + +const FilterFilledIcon = ({size = 24}) => { + return ( + + + + ) +} + +FilterFilledIcon.propTypes = { + size: PropTypes.number, +} + +export default FilterFilledIcon diff --git a/public/img/icons/FilterIcon.js b/public/img/icons/FilterIcon.js new file mode 100644 index 0000000000..f93799dad0 --- /dev/null +++ b/public/img/icons/FilterIcon.js @@ -0,0 +1,27 @@ +import React from 'react' +import PropTypes from 'prop-types' + +const FilterIcon = ({size = 24}) => { + return ( + + + + ) +} + +FilterIcon.propTypes = { + size: PropTypes.number, +} + +export default FilterIcon diff --git a/public/img/icons/FlipBackwardIcon.js b/public/img/icons/FlipBackwardIcon.js new file mode 100644 index 0000000000..2f1aa57296 --- /dev/null +++ b/public/img/icons/FlipBackwardIcon.js @@ -0,0 +1,19 @@ +import React from 'react' +import PropTypes from 'prop-types' + +const FlipBackwardIcon = ({size = 24}) => { + return ( + + + + ) +} + +FlipBackwardIcon.propTypes = { + size: PropTypes.number, +} + +export default FlipBackwardIcon diff --git a/public/img/icons/GoToIcon.js b/public/img/icons/GoToIcon.js new file mode 100644 index 0000000000..9678915b38 --- /dev/null +++ b/public/img/icons/GoToIcon.js @@ -0,0 +1,25 @@ +import React from 'react' +import PropTypes from 'prop-types' + +const GoToIcon = ({size = 24}) => { + return ( + + + + ) +} + +GoToIcon.propTypes = { + size: PropTypes.number, +} + +export default GoToIcon diff --git a/public/img/icons/InfoIcon.js b/public/img/icons/InfoIcon.js index 6f8b91c10d..6882a174f4 100644 --- a/public/img/icons/InfoIcon.js +++ b/public/img/icons/InfoIcon.js @@ -1,13 +1,13 @@ import React from 'react' import PropTypes from 'prop-types' -const InfoIcon = ({size = 16}) => { +const InfoIcon = ({size = 24}) => { return ( - + diff --git a/public/img/icons/More.js b/public/img/icons/More.js deleted file mode 100644 index 62a465aa4a..0000000000 --- a/public/img/icons/More.js +++ /dev/null @@ -1,37 +0,0 @@ -import React from 'react' -import PropTypes from 'prop-types' - -const More = ({size = 24}) => { - return ( - - - - - - {' '} - - - - - - ) -} - -More.propTypes = { - size: PropTypes.number, -} - -export default More diff --git a/public/img/icons/QAFilledICon.js b/public/img/icons/QAFilledICon.js new file mode 100644 index 0000000000..37997a57bb --- /dev/null +++ b/public/img/icons/QAFilledICon.js @@ -0,0 +1,25 @@ +import React from 'react' +import PropTypes from 'prop-types' + +const QAFilledIcon = ({size = 24}) => { + return ( + + + + ) +} + +QAFilledIcon.propTypes = { + size: PropTypes.number, +} + +export default QAFilledIcon diff --git a/public/img/icons/QAICon.js b/public/img/icons/QAICon.js new file mode 100644 index 0000000000..4662477880 --- /dev/null +++ b/public/img/icons/QAICon.js @@ -0,0 +1,50 @@ +import React from 'react' +import PropTypes from 'prop-types' + +const QAIcon = ({size = 24}) => { + return ( + + + + + + + + + ) +} + +QAIcon.propTypes = { + size: PropTypes.number, +} + +export default QAIcon diff --git a/public/img/icons/QualityReportIcon.js b/public/img/icons/QualityReportIcon.js index 0991b66d47..253e8aa6f3 100644 --- a/public/img/icons/QualityReportIcon.js +++ b/public/img/icons/QualityReportIcon.js @@ -1,12 +1,26 @@ import React from 'react' import PropTypes from 'prop-types' -const QualityReportIcon = ({size = 16}) => { +const QualityReportIcon = ({size = 20}) => { return ( - + + ) diff --git a/public/img/icons/ReviseIssuesIcon.js b/public/img/icons/ReviseIssuesIcon.js index 48ccb1a533..c1681303e6 100644 --- a/public/img/icons/ReviseIssuesIcon.js +++ b/public/img/icons/ReviseIssuesIcon.js @@ -15,7 +15,7 @@ const ReviseIssuesIcon = ({size = 18}) => { fillRule="evenodd" clipRule="evenodd" d="M9 2.25C5.27208 2.25 2.25 5.27208 2.25 9C2.25 12.7279 5.27208 15.75 9 15.75C12.7279 15.75 15.75 12.7279 15.75 9C15.75 5.27208 12.7279 2.25 9 2.25ZM0.75 9C0.75 4.44365 4.44365 0.75 9 0.75C13.5563 0.75 17.25 4.44365 17.25 9C17.25 13.5563 13.5563 17.25 9 17.25C4.44365 17.25 0.75 13.5563 0.75 9ZM9 5.25C9.41421 5.25 9.75 5.58579 9.75 6V9C9.75 9.41421 9.41421 9.75 9 9.75C8.58579 9.75 8.25 9.41421 8.25 9V6C8.25 5.58579 8.58579 5.25 9 5.25ZM8.25 12C8.25 11.5858 8.58579 11.25 9 11.25H9.0075C9.42171 11.25 9.7575 11.5858 9.7575 12C9.7575 12.4142 9.42171 12.75 9.0075 12.75H9C8.58579 12.75 8.25 12.4142 8.25 12Z" - fill="#29292D" + fill="currentColor" /> diff --git a/public/img/icons/Search.js b/public/img/icons/Search.js index b08c0adc67..352e55209a 100644 --- a/public/img/icons/Search.js +++ b/public/img/icons/Search.js @@ -3,10 +3,17 @@ import PropTypes from 'prop-types' const Search = ({size = 24}) => { return ( - + diff --git a/public/img/icons/SearchFilled.js b/public/img/icons/SearchFilled.js new file mode 100644 index 0000000000..f9af643943 --- /dev/null +++ b/public/img/icons/SearchFilled.js @@ -0,0 +1,19 @@ +import React from 'react' +import PropTypes from 'prop-types' + +const SearchFilled = ({size = 24}) => { + return ( + + + + ) +} + +SearchFilled.propTypes = { + size: PropTypes.number, +} + +export default SearchFilled diff --git a/public/img/icons/SegmentQA.js b/public/img/icons/SegmentQA.js index fa35f70c3b..f21c905717 100644 --- a/public/img/icons/SegmentQA.js +++ b/public/img/icons/SegmentQA.js @@ -3,19 +3,19 @@ import PropTypes from 'prop-types' const SegmentQA = ({size = 18}) => { return ( - - - - - - - - - + + ) } diff --git a/public/img/icons/SettingsIcon.js b/public/img/icons/SettingsIcon.js new file mode 100644 index 0000000000..de072982bb --- /dev/null +++ b/public/img/icons/SettingsIcon.js @@ -0,0 +1,27 @@ +import React from 'react' +import PropTypes from 'prop-types' + +const SettingsIcon = ({size = 16}) => { + return ( + + + + ) +} + +SettingsIcon.propTypes = { + size: PropTypes.number, +} + +export default SettingsIcon diff --git a/public/img/icons/TranslatedIcon.js b/public/img/icons/TranslatedIcon.js index ea2beafe97..06bafbc355 100644 --- a/public/img/icons/TranslatedIcon.js +++ b/public/img/icons/TranslatedIcon.js @@ -1,20 +1,21 @@ import React from 'react' import PropTypes from 'prop-types' -const TranslatedIcon = ({}) => { +const TranslatedIcon = ({size = 40}) => { return ( - - - - - - + + ) } diff --git a/public/img/icons/icon-3dots.svg b/public/img/icons/icon-3dots.svg deleted file mode 100644 index e2c262e750..0000000000 --- a/public/img/icons/icon-3dots.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/img/icons/icon-QA-line.svg b/public/img/icons/icon-QA-line.svg deleted file mode 100644 index 20c2efbe52..0000000000 --- a/public/img/icons/icon-QA-line.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/img/icons/icon-QA.svg b/public/img/icons/icon-QA.svg deleted file mode 100644 index a00b0ced8a..0000000000 --- a/public/img/icons/icon-QA.svg +++ /dev/null @@ -1,3 +0,0 @@ - - QA - \ No newline at end of file diff --git a/public/img/icons/icon-QR-line.svg b/public/img/icons/icon-QR-line.svg deleted file mode 100644 index 4f7c664626..0000000000 --- a/public/img/icons/icon-QR-line.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/img/icons/icon-QR.svg b/public/img/icons/icon-QR.svg deleted file mode 100644 index 5f52e1c1d6..0000000000 --- a/public/img/icons/icon-QR.svg +++ /dev/null @@ -1,3 +0,0 @@ - - QR - \ No newline at end of file diff --git a/public/img/icons/icon-check.svg b/public/img/icons/icon-check.svg deleted file mode 100644 index 628b05fb24..0000000000 --- a/public/img/icons/icon-check.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/img/icons/icon-comments.svg b/public/img/icons/icon-comments.svg deleted file mode 100644 index bfe42e60e4..0000000000 --- a/public/img/icons/icon-comments.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/img/icons/icon-down.svg b/public/img/icons/icon-down.svg deleted file mode 100644 index 9c3d8aca19..0000000000 --- a/public/img/icons/icon-down.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/img/icons/icon-download-complete.svg b/public/img/icons/icon-download-complete.svg deleted file mode 100644 index 1572aa4ce3..0000000000 --- a/public/img/icons/icon-download-complete.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/img/icons/icon-download.svg b/public/img/icons/icon-download.svg deleted file mode 100644 index 2042789069..0000000000 --- a/public/img/icons/icon-download.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/img/icons/icon-filter-active.svg b/public/img/icons/icon-filter-active.svg deleted file mode 100644 index fc7621a4a9..0000000000 --- a/public/img/icons/icon-filter-active.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/img/icons/icon-filter.svg b/public/img/icons/icon-filter.svg deleted file mode 100644 index 13b1f14a1e..0000000000 --- a/public/img/icons/icon-filter.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/img/icons/icon-folder.svg b/public/img/icons/icon-folder.svg deleted file mode 100644 index 8c4231f9e8..0000000000 --- a/public/img/icons/icon-folder.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/img/icons/icon-manage.svg b/public/img/icons/icon-manage.svg deleted file mode 100644 index 3a42bf643d..0000000000 --- a/public/img/icons/icon-manage.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/img/icons/icon-mark-active.svg b/public/img/icons/icon-mark-active.svg deleted file mode 100644 index 645739717c..0000000000 --- a/public/img/icons/icon-mark-active.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/img/icons/icon-mark.svg b/public/img/icons/icon-mark.svg deleted file mode 100644 index f17fe1624e..0000000000 --- a/public/img/icons/icon-mark.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/img/icons/icon-search-active.svg b/public/img/icons/icon-search-active.svg deleted file mode 100644 index 0c2eae940f..0000000000 --- a/public/img/icons/icon-search-active.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/img/icons/icon-search.svg b/public/img/icons/icon-search.svg deleted file mode 100644 index d38fe37069..0000000000 --- a/public/img/icons/icon-search.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/img/icons/icon-settings.svg b/public/img/icons/icon-settings.svg deleted file mode 100644 index e81bffeadb..0000000000 --- a/public/img/icons/icon-settings.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/img/icons/icon-upload-main-page.svg b/public/img/icons/icon-upload-main-page.svg deleted file mode 100644 index 552ba250d3..0000000000 --- a/public/img/icons/icon-upload-main-page.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/img/icons/icon-upload.svg b/public/img/icons/icon-upload.svg deleted file mode 100644 index 064980b5d4..0000000000 --- a/public/img/icons/icon-upload.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/img/icons/icon-user-logout.svg b/public/img/icons/icon-user-logout.svg deleted file mode 100644 index da354847b1..0000000000 --- a/public/img/icons/icon-user-logout.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/img/info.png b/public/img/info.png deleted file mode 100644 index af08cd56db..0000000000 Binary files a/public/img/info.png and /dev/null differ diff --git a/public/img/jobarchived.png b/public/img/jobarchived.png deleted file mode 100644 index 98557615a7..0000000000 Binary files a/public/img/jobarchived.png and /dev/null differ diff --git a/public/img/jobcancelled.png b/public/img/jobcancelled.png deleted file mode 100644 index 07e595ffca..0000000000 Binary files a/public/img/jobcancelled.png and /dev/null differ diff --git a/public/img/lexiqa-new-2_old.png b/public/img/lexiqa-new-2_old.png deleted file mode 100644 index fc7b226ad9..0000000000 Binary files a/public/img/lexiqa-new-2_old.png and /dev/null differ diff --git a/public/img/logo-drive-16.png b/public/img/logo-drive-16.png deleted file mode 100644 index d7cfffea65..0000000000 Binary files a/public/img/logo-drive-16.png and /dev/null differ diff --git a/public/img/logo_matecat_big.png b/public/img/logo_matecat_big.png deleted file mode 100644 index c3d343b8ad..0000000000 Binary files a/public/img/logo_matecat_big.png and /dev/null differ diff --git a/public/img/logo_matecat_big_translated.svg b/public/img/logo_matecat_big_translated.svg deleted file mode 100644 index cb1e651f8f..0000000000 --- a/public/img/logo_matecat_big_translated.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/img/logo_matecat_big_white.png b/public/img/logo_matecat_big_white.png deleted file mode 100644 index 32a3e4d3d9..0000000000 Binary files a/public/img/logo_matecat_big_white.png and /dev/null differ diff --git a/public/img/matecat_cat.svg b/public/img/matecat_cat.svg deleted file mode 100644 index 2b0513a76f..0000000000 --- a/public/img/matecat_cat.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/img/matecat_file_icons.png b/public/img/matecat_file_icons.png deleted file mode 100644 index 0b64c85d11..0000000000 Binary files a/public/img/matecat_file_icons.png and /dev/null differ diff --git a/public/img/matecat_file_icons2x.png b/public/img/matecat_file_icons2x.png deleted file mode 100644 index b6f476c0bf..0000000000 Binary files a/public/img/matecat_file_icons2x.png and /dev/null differ diff --git a/public/img/matecat_file_icons_ts.png b/public/img/matecat_file_icons_ts.png deleted file mode 100644 index 97a6199d2d..0000000000 Binary files a/public/img/matecat_file_icons_ts.png and /dev/null differ diff --git a/public/img/matecat_file_icons_ts2x.png b/public/img/matecat_file_icons_ts2x.png deleted file mode 100644 index 021b93db0e..0000000000 Binary files a/public/img/matecat_file_icons_ts2x.png and /dev/null differ diff --git a/public/img/matecat_smiling.png b/public/img/matecat_smiling.png deleted file mode 100644 index 4d5b7fe046..0000000000 Binary files a/public/img/matecat_smiling.png and /dev/null differ diff --git a/public/img/matecat_watch-left-border.png b/public/img/matecat_watch-left-border.png deleted file mode 100644 index 38c923805f..0000000000 Binary files a/public/img/matecat_watch-left-border.png and /dev/null differ diff --git a/public/img/matecat_watch.png b/public/img/matecat_watch.png deleted file mode 100644 index 3e419cca16..0000000000 Binary files a/public/img/matecat_watch.png and /dev/null differ diff --git a/public/img/offline2.png b/public/img/offline2.png deleted file mode 100644 index dd203fd77c..0000000000 Binary files a/public/img/offline2.png and /dev/null differ diff --git a/public/img/progressbar-green.gif b/public/img/progressbar-green.gif deleted file mode 100644 index 3dd5919327..0000000000 Binary files a/public/img/progressbar-green.gif and /dev/null differ diff --git a/public/img/progressbar.gif b/public/img/progressbar.gif deleted file mode 100644 index 1477bc7970..0000000000 Binary files a/public/img/progressbar.gif and /dev/null differ diff --git a/public/img/soft-return1.png b/public/img/soft-return1.png deleted file mode 100644 index aea9c45ba3..0000000000 Binary files a/public/img/soft-return1.png and /dev/null differ diff --git a/public/img/x.png b/public/img/x.png deleted file mode 100644 index 04eb500294..0000000000 Binary files a/public/img/x.png and /dev/null differ diff --git a/public/js/api/downloadAnalysisReport/downloadAnalysisReport.js b/public/js/api/downloadAnalysisReport/downloadAnalysisReport.js new file mode 100644 index 0000000000..8e05280004 --- /dev/null +++ b/public/js/api/downloadAnalysisReport/downloadAnalysisReport.js @@ -0,0 +1,53 @@ +import {getMatecatApiDomain} from '../../utils/getMatecatApiDomain' + +/** + * Download Analysis Report + * + * @param {Object} options + * @param {string} options.idProject + * @param {string} options.password + * @param {string} [options.downloadType='XTRF'] + * @returns {Promise} + */ +export const downloadAnalysisReport = async ({ + idProject, + password, + downloadType = 'XTRF', +}) => { + const response = await fetch( + `${getMatecatApiDomain()}api/app/download-analysis-report`, + { + method: 'POST', + credentials: 'include', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + body: new URLSearchParams({ + id_project: idProject, + password, + download_type: downloadType, + }), + }, + ) + + if (!response.ok) return Promise.reject(response) + + const blob = await response.blob() + const contentDisposition = response.headers.get('Content-Disposition') + let filename = 'analysis-report.zip' + if (contentDisposition) { + const match = contentDisposition.match(/filename="?([^";\n]+)"?/) + if (match?.[1]) { + filename = match[1] + } + } + + const url = window.URL.createObjectURL(blob) + const link = document.createElement('a') + link.href = url + link.download = filename + document.body.appendChild(link) + link.click() + link.remove() + window.URL.revokeObjectURL(url) +} diff --git a/public/js/api/downloadAnalysisReport/index.js b/public/js/api/downloadAnalysisReport/index.js new file mode 100644 index 0000000000..acd3163130 --- /dev/null +++ b/public/js/api/downloadAnalysisReport/index.js @@ -0,0 +1 @@ +export * from './downloadAnalysisReport' diff --git a/public/js/components/analyze/AnalyzeChunksResume.js b/public/js/components/analyze/AnalyzeChunksResume.js index 44d28d8dd1..33ac8e61ff 100644 --- a/public/js/components/analyze/AnalyzeChunksResume.js +++ b/public/js/components/analyze/AnalyzeChunksResume.js @@ -1,650 +1,253 @@ -import React, {useRef} from 'react' -import {isUndefined, size} from 'lodash' -import {each, map} from 'lodash/collection' -import {pick} from 'lodash/object' -import $ from 'jquery' -import {Popup} from 'semantic-ui-react' -import OutsourceContainer from '../outsource/OutsourceContainer' +import React, {useRef, useState, useEffect, useCallback} from 'react' import ModalsActions from '../../actions/ModalsActions' -import TranslatedIcon from '../../../img/icons/TranslatedIcon' -import Tooltip from '../common/Tooltip' import CommonUtils from '../../utils/commonUtils' -import { - ANALYSIS_STATUS, - ANALYSIS_WORKFLOW_TYPES, - UNIT_COUNT, -} from '../../constants/Constants' +import {ANALYSIS_STATUS} from '../../constants/Constants' import UserStore from '../../stores/UserStore' -import LabelWithTooltip from '../common/LabelWithTooltip' -import Split from '../../../img/icons/Split' -import Merge from '../../../img/icons/Merge' -import HelpCircle from '../../../img/icons/HelpCircle' - -class AnalyzeChunksResume extends React.Component { - constructor(props) { - super(props) - this.payableValues = [] - this.payableValuesChenged = [] - this.containers = {} - this.state = { - openOutsource: false, - outsourceJobId: null, - } - - this.jobLinkRef = {} - } - - showDetails = (idJob) => (evt) => { - if ($(evt.target).parents('.outsource-container').length === 0) { - evt.preventDefault() - evt.stopPropagation() - this.props.openAnalysisReport(idJob, true) - } - } - openSplitModal = (id) => (e) => { - e.stopPropagation() - e.preventDefault() - const {project} = this.props - let job = project.get('jobs').find((item) => { - return item.get('id') === id - }) - ModalsActions.openSplitJobModal(job, project, () => - window.location.reload(), - ) - } - - openMergeModal = (id) => (e) => { - e.stopPropagation() - e.preventDefault() - const {project} = this.props - let job = this.props.project.get('jobs').find((item) => { - return item.get('id') === id - }) - ModalsActions.openMergeModal(project.toJS(), job.toJS(), () => - window.location.reload(), - ) - } - - thereIsChunkOutsourced = () => { - const {idJob} = this.props - let outsourceChunk = this.props.project.get('jobs').find((item) => { - return !!item.get('outsource') && item.get('id') === idJob - }) - return !isUndefined(outsourceChunk) - } - - getTranslateUrl = (job, index) => { - let chunk_id = index ? index : job.get('id') - return ( - '/translate/' + - this.props.project.get('project_slug') + - '/' + - job.get('source') + - '-' + - job.get('target') + - '/' + - chunk_id + - '-' + - job.get('password') + - (index ? '#' + job.get('job_first_segment') : '') - ) - } +import {Button, BUTTON_SIZE, BUTTON_TYPE} from '../common/Button/Button' +import CompareTableHeader from './CompareTableHeader' +import SingleChunkJob from './SingleChunkJob' +import SplitChunkJob from './SplitChunkJob' + +const AnalyzeChunksResume = ({ + project, + status, + jobsAnalysis, + idJob, + openAnalysisReport, +}) => { + const payableValues = useRef({}) + const payableValuesChanged = useRef({}) + const containers = useRef({}) + const jobLinkRef = useRef({}) + + const [openOutsource, setOpenOutsource] = useState(false) + const [outsourceJobId, setOutsourceJobId] = useState(null) + + const showDetails = useCallback( + (jobId) => (evt) => { + if (!evt.target.closest('.outsource-container')) { + evt.preventDefault() + evt.stopPropagation() + openAnalysisReport(jobId, true) + } + }, + [openAnalysisReport], + ) - openOutsourceModal = (idJob, chunk) => (e) => { - const {status} = this.props - e.stopPropagation() - e.preventDefault() - if (status !== ANALYSIS_STATUS.DONE) return + const openSplitModal = useCallback( + (id) => (e) => { + e.stopPropagation() + e.preventDefault() + const job = project.get('jobs').find((item) => item.get('id') === id) + ModalsActions.openSplitJobModal(job, project, () => + window.location.reload(), + ) + }, + [project], + ) - const data = { - event: 'outsource_request', - } - CommonUtils.dispatchAnalyticsEvents(data) - if (chunk.outsource_available) { - this.setState({ - openOutsource: true, - outsourceJobId: idJob, - }) - } else { - window.open('https://translated.com/contact-us', '_blank') - } - } + const openMergeModal = useCallback( + (id) => (e) => { + e.stopPropagation() + e.preventDefault() + const job = project.get('jobs').find((item) => item.get('id') === id) + ModalsActions.openMergeModal(project.toJS(), job.toJS(), () => + window.location.reload(), + ) + }, + [project], + ) - closeOutsourceModal = () => { - this.setState({ - openOutsource: false, - outsourceJobId: null, - }) - } + const thereIsChunkOutsourced = useCallback(() => { + const outsourceChunk = project + .get('jobs') + .find((item) => !!item.get('outsource') && item.get('id') === idJob) + return outsourceChunk !== undefined + }, [project, idJob]) + + const handleOpenOutsourceModal = useCallback( + (jobId, chunk) => (e) => { + e.stopPropagation() + e.preventDefault() + if (status !== ANALYSIS_STATUS.DONE) return + + CommonUtils.dispatchAnalyticsEvents({event: 'outsource_request'}) + if (chunk.outsource_available) { + setOpenOutsource(true) + setOutsourceJobId(jobId) + } else { + window.open('https://translated.com/contact-us', '_blank') + } + }, + [status], + ) - checkPayableChanged = (idJob, payable) => { - if (this.payableValues[idJob] && payable !== this.payableValues[idJob]) { - this.payableValuesChenged[idJob] = true + const closeOutsourceModal = useCallback(() => { + setOpenOutsource(false) + setOutsourceJobId(null) + }, []) + + const checkPayableChanged = useCallback((jobId, payable) => { + if ( + payableValues.current[jobId] && + payable !== payableValues.current[jobId] + ) { + payableValuesChanged.current[jobId] = true } - this.payableValues[idJob] = payable - } - - copyJobLinkToClipboard = (jid) => (e) => { - e.stopPropagation() - this.jobLinkRef[jid].select() - this.jobLinkRef[jid].setSelectionRange(0, 99999) - document.execCommand('copy') - } + payableValues.current[jobId] = payable + }, []) + + const copyJobLinkToClipboard = useCallback( + (jid) => (e) => { + e.stopPropagation() + const url = jobLinkRef.current[jid]?.value + if (url) { + navigator.clipboard.writeText(url) + } + }, + [], + ) - goToTranslate = (chunk, index, e) => { + const goToTranslate = useCallback((chunk, index, e) => { e.preventDefault() e.stopPropagation() - const key = 'first_translate_click' + config.id_project + const key = `first_translate_click${config.id_project}` if (!sessionStorage.getItem(key)) { - //Track Translate click const userInfo = UserStore.getUser() if (userInfo) { - const event = { + CommonUtils.dispatchAnalyticsEvents({ event: 'open_job', userStatus: 'loggedUser', userId: userInfo.user.uid, idProject: parseInt(config.id_project), - } - CommonUtils.dispatchAnalyticsEvents(event) + }) sessionStorage.setItem(key, 'true') } } window.open(chunk.urls.t, '_blank') - } - - getDirectOpenButton = (chunk, index) => { - const {status} = this.props - return ( -
{ - this.goToTranslate(chunk, index, e) - }} + }, []) + + const getDirectOpenButton = useCallback( + (chunk, index) => ( +
- ) - } - - getOutsourceButton = (chunk, index) => { - return ( - - ) - } - - getResumeJobs = () => { - const {copyJobLinkToClipboard, thereIsChunkOutsourced} = this - const {status, jobsAnalysis} = this.props - - let buttonsClass = - status !== 'DONE' || thereIsChunkOutsourced() ? 'disabled' : '' - if (jobsAnalysis) { - return jobsAnalysis.map((job, indexJob) => { - if (job.chunks.length > 1) { - let chunksHtml = map(job.chunks, (chunkAnalysis, index) => { - chunkAnalysis.id = job.id - chunkAnalysis.outsource_available = job.outsource_available - chunkAnalysis.target_name = job.target_name - chunkAnalysis.source_name = job.source_name - index++ - - let openOutsource = - this.state.openOutsource && - this.state.outsourceJobId === job.id + '-' + index - let chunkJob = this.props.project.get('jobs').find((item) => { - return ( - item.get('id') === chunkAnalysis.id && - item.get('password') === chunkAnalysis.password - ) - }) - this.checkPayableChanged( - job.id + index, - chunkAnalysis.total_equivalent, - ) - - let openOutsourceClass = openOutsource ? 'openOutsource' : '' - const jidChunk = `${chunkAnalysis.id}-${index}` - - return ( -
-
-
{'Chunk ' + index}
-
- (this.jobLinkRef[jidChunk] = el)} - type="text" - readOnly - value={encodeURI(chunkAnalysis.urls.t)} - onClick={(e) => e.stopPropagation()} - /> - - - - } - /> -
-
-
-
-
{chunkAnalysis.total_raw}
-
- {this.props.project.get('analysis').get('workflow_type') === - ANALYSIS_WORKFLOW_TYPES.STANDARD && ( -
-
{chunkAnalysis.total_industry}
-
- )} -
- (this.containers[chunkAnalysis.id + index] = container) - } - > -
{chunkAnalysis.total_equivalent}
-
-
-
-
- {/*{self.getOpenButton(job.toJS(), job.id + '-' + index)}*/} - {this.getDirectOpenButton( - chunkAnalysis, - job.id + '-' + index, - )} -
- {!config.jobAnalysis && - this.getOutsourceButton( - chunkAnalysis, - chunkAnalysis.id + '-' + index, - )} -
- -
- ) - }) - - return ( -
-
-
-
-
-
- ID: {jobsAnalysis[indexJob].id} -
-
- - {jobsAnalysis[indexJob].source_name} - -
- -
- - {jobsAnalysis[indexJob].target_name} - -
-
-
- -
-
- - Merge -
-
-
- {chunksHtml} -
-
- ) - } else { - let chunkAnalysis = jobsAnalysis[indexJob].chunks[0] - chunkAnalysis.id = job.id - chunkAnalysis.outsource_available = job.outsource_available - chunkAnalysis.outsource = job.outsource - chunkAnalysis.target_name = job.target_name - chunkAnalysis.source_name = job.source_name - let total_raw = chunkAnalysis.total_raw - let standardWordCount = chunkAnalysis.total_industry - let chunkJob = this.props.project.get('jobs').find((item) => { - return ( - item.get('id') === chunkAnalysis.id && - item.get('password') === chunkAnalysis.password - ) - }) - let total_standard = standardWordCount ? standardWordCount : 0 - - let openOutsource = - this.state.openOutsource && - this.state.outsourceJobId === jobsAnalysis[indexJob].id - let openOutsourceClass = openOutsource ? 'openOutsource' : '' - - this.checkPayableChanged( - jobsAnalysis[indexJob].id, - chunkAnalysis.total_equivalent, - ) + + ), + [status, goToTranslate], + ) - return ( -
-
-
-
-
-
- ID: {jobsAnalysis[indexJob].id} -
-
- - {jobsAnalysis[indexJob].source_name} - -
- -
- - {jobsAnalysis[indexJob].target_name} - -
-
-
- - (this.jobLinkRef[jobsAnalysis[indexJob].id] = el) - } - onClick={(e) => e.stopPropagation()} - /> - -
-
-
-
- {/*
Total words:
*/} -
{total_raw}
+ const workflowType = project.get('analysis').get('workflow_type') + const countUnit = jobsAnalysis?.[0]?.count_unit + + const sharedProps = { + project, + status, + openOutsource, + outsourceJobId, + showDetails, + checkPayableChanged, + copyJobLinkToClipboard, + getDirectOpenButton, + closeOutsourceModal, + handleOpenOutsourceModal, + jobLinkRef, + containers, + } + + const renderJobs = () => { + if (!jobsAnalysis) { + return project.get('jobs').map((jobInfo, indexJob) => ( +
+ +
+
+
+
+
+
+
0
- {this.props.project.get('analysis').get('workflow_type') === - ANALYSIS_WORKFLOW_TYPES.STANDARD && ( -
- {/*
Other CAT tool
*/} -
{total_standard}
-
- )} -
- (this.containers[jobsAnalysis[indexJob].id] = container) - } - > - {/*
Weighted words:
*/} -
- {/**/} - {chunkAnalysis.total_equivalent} -
+
+
0
-
-
-
- {!config.jobAnalysis && config.splitEnabled ? ( -
- - Split -
- ) : null} - {/*{this.getOpenButton(job.toJS(), jobsAnalysis[indexJob].id)}*/} - {this.getDirectOpenButton(chunkAnalysis)} +
+
0
- {!config.jobAnalysis && - this.getOutsourceButton(chunkAnalysis, chunkAnalysis.id)}
+
- -
-
- ) - } - }) - } else { - return this.props.project.get('jobs').map((jobInfo, indexJob) => { - return ( -
-
-
-
-
- - {jobInfo.get('sourceTxt')} - -
- -
- - {jobInfo.get('targetTxt')} - -
-
-
-
-
0
-
-
-
0
-
-
-
0
-
-
-
- ) - }) +
+ )) } - } - openAnalysisReport = (e) => { - e.preventDefault() - e.stopPropagation() - this.props.openAnalysisReport() + return jobsAnalysis.map((job, indexJob) => { + const isSplit = job.chunks.length > 1 + + return ( +
+ + {isSplit ? ( + + ) : ( + + )} +
+ ) + }) } - componentDidUpdate() { - let changedData = pick(this.payableValuesChenged, (item) => { - return item === true - }) - if (size(changedData) > 0) { - each(changedData, (item, i) => { - this.containers[i].classList.add('updated-count') - setTimeout(() => { - this.containers[i].classList.remove('updated-count') - }, 400) + // Animate payable value changes on update + useEffect(() => { + const changed = payableValuesChanged.current + const changedKeys = Object.keys(changed).filter((key) => changed[key]) + + if (changedKeys.length > 0) { + changedKeys.forEach((key) => { + const el = containers.current[key] + if (el) { + el.classList.add('updated-count') + setTimeout(() => el.classList.remove('updated-count'), 400) + } }) } - } - - componentDidMount() { - if (this.props.status === 'DONE') { - each(self.containers, (item, i) => { - this.classList.add('updated-count') - setTimeout(() => { - this.containers[i].classList.remove('updated-count') - }, 400) + }) + + // Initial animation on mount when analysis is done + useEffect(() => { + if (status === 'DONE') { + Object.entries(containers.current).forEach(([, el]) => { + if (el) { + el.classList.add('updated-count') + setTimeout(() => el.classList.remove('updated-count'), 400) + } }) } - } + }, []) // eslint-disable-line react-hooks/exhaustive-deps - render() { - let showHideText = this.props.showAnalysis ? 'Hide Details' : 'Show Details' - let iconClass = this.props.showAnalysis ? 'open' : '' - let html = this.getResumeJobs() - return ( -
-
-
-
-
-

-

-
- {this.props.jobsAnalysis.length && - this.props.jobsAnalysis[0].count_unit === UNIT_COUNT.WORDS ? ( -
-
Total word count
-
- ) : ( -
-
Total character count
-
- )} - {this.props.project.get('analysis').get('workflow_type') === - ANALYSIS_WORKFLOW_TYPES.STANDARD && ( -
-
- Industry weighted - - - -
-
- )} -
-
Matecat weighted
-
-
-
-
-
{html}
- {this.props.jobsAnalysis ? ( -
-
-

{showHideText}

-
- -
-
-
- ) : null} -
- ) - } -} - -const OutsourceButton = ({chunk, index, openOutsourceModal, status}) => { - const outsourceButton = useRef() - return !chunk.outsource_available && - chunk.outsource_info?.custom_payable_rate ? ( -
- - Jobs created with custom billing models cannot be outsourced to - Translated. -
- In order to outsource this job to Translated, please recreate it - using Matecat's standard billing model -
- } - > -
- Buy Translation - - from - -
- -
- ) : ( -
- Buy Translation - - from - -
+ return ( +
{renderJobs()}
) } diff --git a/public/js/components/analyze/AnalyzeHeader.js b/public/js/components/analyze/AnalyzeHeader.js index 90a5d22e0b..800c4892bc 100644 --- a/public/js/components/analyze/AnalyzeHeader.js +++ b/public/js/components/analyze/AnalyzeHeader.js @@ -1,52 +1,90 @@ -import React from 'react' -import $ from 'jquery' -import {TransitionGroup, CSSTransition} from 'react-transition-group' +import React, {useRef, useEffect, useCallback} from 'react' import {ANALYSIS_STATUS} from '../../constants/Constants' import {Popup} from 'semantic-ui-react' -import HelpCircle from '../../../img/icons/HelpCircle' +import {downloadAnalysisReport} from '../../api/downloadAnalysisReport' +import {PROGRESS_BAR_SIZE, ProgressBar} from '../common/ProgressBar' +import {Badge, BADGE_TYPE} from '../common/Badge' +import Check from '../../../img/icons/Check' +import Download from '../../../img/icons/Download' +import InfoIcon from '../../../img/icons/InfoIcon' -class AnalyzeHeader extends React.Component { - constructor(props) { - super(props) - this.previousQueueSize = 0 - this.lastProgressSegments = 0 - this.noProgressTail = 0 - this.state = {} - } +const AnalyzeHeader = ({data, project}) => { + const previousQueueSizeRef = useRef(0) + const lastProgressSegmentsRef = useRef(0) + const noProgressTailRef = useRef(0) - getAnalysisStateHtml() { - this.showProgressBar = false + const showProgressBarRef = useRef(false) - let html = ( + const errorAnalysisHtml = useCallback(() => { + let analyzerNotRunningErrorString + if (config.support_mail.indexOf('@') === -1) { + analyzerNotRunningErrorString = ( +

+ The analysis seems not to be running. Contact {config.support_mail}. +

+ ) + } else { + analyzerNotRunningErrorString = ( +

+ The analysis seems not to be running. Contact{' '} + {config.support_mail}. +

+ ) + } + return (
-
-
-
Fast word counting...
+
+ Analysis status: + + + Failed +
+ + {analyzerNotRunningErrorString} + +
+ ) + }, []) + + const handleDownloadAnalysisReport = useCallback(() => { + downloadAnalysisReport({ + idProject: project.get('id'), + password: project.get('password'), + }).catch((error) => { + console.error('Error downloading analysis report:', error) + }) + }, [project]) + + let getAnalysisStateHtml + getAnalysisStateHtml = useCallback(() => { + showProgressBarRef.current = false + + let html = ( +
+
+
Fast word counting...
) - let status = this.props.data.get('status') - let in_queue_before = parseInt(this.props.data.get('in_queue_before')) + let status = data.get('status') + const in_queue_before = parseInt(data.get('in_queue_before')) if (status === 'DONE') { html = (
-
(this.containerAnalysisComplete = container)} - > -
- Analysis: - - complete - -
- - Download Analysis Report - +
+ Analysis status: + + + Complete +
+ + Download Analysis Report + +
) } else if ( @@ -56,42 +94,29 @@ class AnalyzeHeader extends React.Component { in_queue_before > 0 ) { if (config.daemon_warning) { - html = this.errorAnalysisHtml() + html = errorAnalysisHtml() } else if (in_queue_before > 0) { - if (this.previousQueueSize <= in_queue_before) { + if (previousQueueSizeRef.current <= in_queue_before) { html = (
-
-
- - Please wait...{' '} -

There are other projects in queue.

-
-
+
+ + Please wait...{' '} +

There are other projects in queue.

+
) } else { - //decreasing ( TM analysis on another project ) html = (
-
-
- - Please wait... -

- There are still{' '} - - {this.props.data.get('in_queue_before')} - {' '} - segments in queue. -

-
+
+
+ Please wait... +

+ There are still{' '} + {data.get('in_queue_before')}{' '} + segments in queue. +

) @@ -99,46 +124,36 @@ class AnalyzeHeader extends React.Component { } else { html = (
-
-
- - Please wait... -

There are other projects in queue.

-
+
+
+ Please wait... +

There are other projects in queue.

) } - this.previousQueueSize = in_queue_before - } else if (status === 'FAST_OK' && in_queue_before === 0) { - if ( - this.lastProgressSegments !== this.props.data.get('segments_analyzed') - ) { - this.lastProgressSegments = this.props.data.get('segments_analyzed') - this.noProgressTail = 0 - this.showProgressBar = true - html = this.getProgressBarText() + previousQueueSizeRef.current = in_queue_before + } else if (status === ANALYSIS_STATUS.FAST_OK && in_queue_before === 0) { + if (lastProgressSegmentsRef.current !== data.get('segments_analyzed')) { + lastProgressSegmentsRef.current = data.get('segments_analyzed') + noProgressTailRef.current = 0 + showProgressBarRef.current = true + html = getProgressBar() } else { - this.noProgressTail++ - if (this.noProgressTail > 9) { - html = this.errorAnalysisHtml() + noProgressTailRef.current++ + if (noProgressTailRef.current > 9) { + html = errorAnalysisHtml() } } - } else if (status === 'NOT_TO_ANALYZE') { + } else if (status === ANALYSIS_STATUS.NOT_TO_ANALYZE) { html = (
-
-
- We are having issues with the analysis of this project. -
+
+ We are having issues with the analysis of this project.
- {' '} Please contact us at{' '} - {config.support_mail}{' '} + {config.support_mail} {' '} for more information.
@@ -154,104 +169,28 @@ class AnalyzeHeader extends React.Component { {config.support_mail} ) } + html = (
-
- - Ops.. we got an error. No text to translate in the file{' '} - {this.props.data.get('NAME')}. - -
- Contact {error} +
+ Ops.. we got an error. No text to translate in the file . +
Contact {error}
) } else { - // Unknown error :) - html = this.errorAnalysisHtml() + html = errorAnalysisHtml() } return html - } + }, [data, errorAnalysisHtml, getProgressBar]) - errorAnalysisHtml() { - let analyzerNotRunningErrorString - if (config.support_mail.indexOf('@') === -1) { - analyzerNotRunningErrorString = ( -

- The analysis seems not to be running. Contact {config.support_mail}. -

- ) - } else { - analyzerNotRunningErrorString = ( -

- The analysis seems not to be running. Contact{' '} - {config.support_mail}. -

- ) - } - return ( -
-
- {analyzerNotRunningErrorString} -
-
- ) - } - - getProgressBarText() { - return ( -
-
-
Searching for TM Matches
- - {' '} - ({this.props.data.get('segments_analyzed')} of{' '} - - - {' '} - {' ' + this.props.data.get('total_segments')}) - -
-
- ) - } - - getProgressBar() { - if (this.showProgressBar) { - let width = - (this.props.data.get('segments_analyzed') / - this.props.data.get('total_segments')) * - 100 + - '%' - return ( - - ) - } - return null - } - getSavingWorkCount() { - const data = this.props.data.toJS() - const {total_equivalent} = data + const getSavingWorkCount = useCallback(() => { + const dataJS = data.toJS() + const {total_equivalent} = dataJS let wcTime = total_equivalent / 3000 let wcUnit = 'day' if (wcTime > 0 && wcTime < 1) { - wcTime = wcTime * 8 //convert to hours (1 work day = 8 hours) + wcTime = wcTime * 8 wcUnit = 'hour' } if (wcTime > 0 && wcTime < 1) { @@ -262,8 +201,14 @@ class AnalyzeHeader extends React.Component { wcUnit = wcUnit + 's' } return Math.round(wcTime) + ' work ' + wcUnit - } - getWordscount() { + }, [data]) + + const getWordscount = useCallback(() => { + const status = data.get('status') + const inProgress = + status === ANALYSIS_STATUS.FAST_OK && + data.get('in_queue_before') === 0 && + lastProgressSegmentsRef.current !== data.get('total_segments') const tooltipText = ( Matecat suggests MT only when it helps thanks to a dynamic penalty @@ -276,164 +221,101 @@ class AnalyzeHeader extends React.Component { ) - let status = this.props.data.get('status') - let raw_words = this.props.data.get('total_raw'), + let raw_words = data.get('total_raw'), weightedWords = '' if ( (status === ANALYSIS_STATUS.NEW || status === '' || - this.props.data.get('in_queue_before') > 0) && + data.get('in_queue_before') > 0) && config.daemon_warning ) { - weightedWords = this.props.data.get('total_raw') + weightedWords = data.get('total_raw') } else { - if ( - status === ANALYSIS_STATUS.DONE || - this.props.data.get('total_equivalent') > 0 - ) { - weightedWords = this.props.data.get('total_equivalent') + if (status === ANALYSIS_STATUS.DONE || data.get('total_equivalent') > 0) { + weightedWords = data.get('total_equivalent') } if (status === ANALYSIS_STATUS.NOT_TO_ANALYZE) { - weightedWords = this.props.data.get('total_raw') + weightedWords = data.get('total_raw') } } let saving_perc = raw_words > 0 ? parseInt(((raw_words - weightedWords) / raw_words) * 100) + '%' : '0%' - if (saving_perc !== this.saving_perc_value) { - this.updatedSavingWords = true - } - this.saving_perc_value = saving_perc return ( -
-
-
(this.containerSavingWords = container)} - > -

-
{saving_perc}
-
- Saving on word count -
- {this.getSavingWorkCount()} at 3.000 w/day -
-
-

-

- Matecat gives you more matches than any other tool thanks to a - better integration of machine translation and translation - memories. - - - - } - /> -

+
+
+

{saving_perc}

+
+ Saving on word count +
+ {getSavingWorkCount()} at 3.000 w/day +
+ + +
+ } + />
) - } - - downloadAnalysisReport() { - const pid = this.props.project.get('id') - const ppassword = this.props.project.get('password') - - const form = - '
' + - ' ' + - ' ' + - ' ' + - '
' - $('body').append(form) - $('#downloadAnalysisReportForm').submit() - } + }, [data, getSavingWorkCount]) - /** - * To add informations from the plugins - * @returns {string} - */ - moreProjectInfo() { - return '' - } - - componentDidUpdate() { - let self = this - if (this.updatedSavingWords) { - this.containerSavingWords.classList.add('updated-count') - this.updatedSavingWords = false - setTimeout(function () { - self.containerSavingWords.classList.remove('updated-count') - }, 400) - } - let status = this.props.data.get('status') - if (status === ANALYSIS_STATUS.DONE) { - setTimeout(function () { - self.containerAnalysisComplete?.classList.remove('hide') - }, 600) - } - } - - componentDidMount() { - let self = this - let status = this.props.data.get('status') - if (status === ANALYSIS_STATUS.DONE) { - this.containerSavingWords.classList.add('updated-count') - setTimeout(function () { - self.containerSavingWords.classList.remove('updated-count') - self.containerAnalysisComplete?.classList.remove('hide') - }, 400) + const getProgressBar = useCallback(() => { + if (showProgressBarRef.current) { + const progress = + (data.get('segments_analyzed') / data.get('total_segments')) * 100 + return ( +
+ + Searching for TM Matches + + {' '} + ({data.get('segments_analyzed')} of{' '} + + + {' '} + {data.get('total_segments')}) + +
+ } + className={'analysis-progressbar'} + /> +
+ ) } - } + return null + }, [data]) - shouldComponentUpdate(nextProps) { - return !nextProps.data.equals(this.props.data) - } + const analysisStateHtml = getAnalysisStateHtml() + const wordsCountHtml = getWordscount() + const projectName = project.get('name') ? project.get('name') : '' - render() { - let analysisStateHtml = this.getAnalysisStateHtml() - let wordsCountHtml = this.getWordscount() - let projectName = this.props.project.get('name') - ? this.props.project.get('name') - : '' - return ( -
-
-

Volume Analysis

-
-
- {' '} - {projectName}{' '} -
-
- {this.moreProjectInfo()} - {analysisStateHtml} + return ( +
+
+
+
{projectName}
- -
{wordsCountHtml}
- - {this.getProgressBar()} + {analysisStateHtml}
- ) - } + {wordsCountHtml} +
+ ) } -export default AnalyzeHeader +export default React.memo(AnalyzeHeader, (prevProps, nextProps) => { + return nextProps.data.equals(prevProps.data) +}) diff --git a/public/js/components/analyze/AnalyzeMain.js b/public/js/components/analyze/AnalyzeMain.js index d30f858f93..f1fd43ceb9 100644 --- a/public/js/components/analyze/AnalyzeMain.js +++ b/public/js/components/analyze/AnalyzeMain.js @@ -4,9 +4,10 @@ import $ from 'jquery' import AnalyzeHeader from './AnalyzeHeader' import AnalyzeChunksResume from './AnalyzeChunksResume' import ProjectAnalyze from './ProjectAnalyze' +import {Button} from '../common/Button/Button' +import {SpinnerLoader} from '../common/SpinnerLoader' -const AnalyzeMain = ({volumeAnalysis, project, parentRef}) => { - const [showAnalysis, setShowAnalysis] = useState(false) +const AnalyzeMain = ({volumeAnalysis, project}) => { const [intervalId, setIntervalId] = useState() const [scrollTop, setScrollTop] = useState() const [jobToScroll, setJobToScroll] = useState() @@ -23,18 +24,15 @@ const AnalyzeMain = ({volumeAnalysis, project, parentRef}) => { const spinner = (
-
-
Loading Volume Analysis
-
+
) - const openAnalysisReport = (idJob, forceOpen) => { - setShowAnalysis((showAnalysis) => (forceOpen ? forceOpen : !showAnalysis)) + const openAnalysisReport = (idJob) => { setJobToScroll(idJob) } - const scrollStep = () => { + /* const scrollStep = () => { if (window.pageYOffset === 0) { clearInterval(intervalId) } @@ -55,60 +53,45 @@ const AnalyzeMain = ({volumeAnalysis, project, parentRef}) => { parentRef.current && parentRef.current.removeEventListener('scroll', handleScroll) } - }) + })*/ return ( -
+
{volumeAnalysis && project ? ( -
-
-
- +

Volume Analysis

+ + {volumeAnalysis.get('jobs').size > 0 ? ( + <> + -
- {volumeAnalysis.get('jobs').size > 0 ? ( - <> - {' '} - +
Job details
+ - {showAnalysis ? ( -
- {/* - */} - - {/* - */} -
- ) : null} - - ) : null} -
- {scrollTop > 200 ? ( - - ) : null} + + ) : null}*/}
) : ( spinner diff --git a/public/js/components/analyze/ChunkAnalyzeFile.js b/public/js/components/analyze/ChunkAnalyzeFile.js index fc72464f56..cda1524117 100644 --- a/public/js/components/analyze/ChunkAnalyzeFile.js +++ b/public/js/components/analyze/ChunkAnalyzeFile.js @@ -18,14 +18,11 @@ const ChunkAnalyzeFile = ({file, index, size, rates, workflowType}) => { className={`chunk-file-detail-background ${size === index ? 'last' : ''} `} />
-
-
- -
- - {file.name} - -
+ + + + {file.name} +
{matches.find((item) => item.type === 'new').equivalent}
diff --git a/public/js/components/analyze/ChunkAnalyzeHeader.js b/public/js/components/analyze/ChunkAnalyzeHeader.js index 803e2daf6d..2105ea9496 100644 --- a/public/js/components/analyze/ChunkAnalyzeHeader.js +++ b/public/js/components/analyze/ChunkAnalyzeHeader.js @@ -22,12 +22,11 @@ const ChunkAnalyzeHeader = ({ : '' }`} > - {showFiles &&
}
- {chunksSize > 1 ? '#' + index : ''} + {chunksSize > 1 ? 'Chunk ' + index : ''} Raw
@@ -118,12 +117,11 @@ const ChunkAnalyzeHeader = ({
) : workflowType === ANALYSIS_WORKFLOW_TYPES.MTQE ? (
- {showFiles &&
}
- {chunksSize > 1 ? '#' + index : ''} + {chunksSize > 1 ? 'Chunk ' + index : ''} Raw
diff --git a/public/js/components/analyze/CompareTableHeader.js b/public/js/components/analyze/CompareTableHeader.js new file mode 100644 index 0000000000..12e7d38f73 --- /dev/null +++ b/public/js/components/analyze/CompareTableHeader.js @@ -0,0 +1,91 @@ +import React, {createRef} from 'react' +import {ANALYSIS_WORKFLOW_TYPES, UNIT_COUNT} from '../../constants/Constants' +import HelpCircle from '../../../img/icons/HelpCircle' +import { + Button, + BUTTON_MODE, + BUTTON_SIZE, + BUTTON_TYPE, +} from '../common/Button/Button' +import Merge from '../../../img/icons/Merge' +import Split from '../../../img/icons/Split' +import ChevronRight from '../../../img/icons/ChevronRight' +import Tooltip from '../common/Tooltip' + +const CompareTableHeader = ({ + countUnit, + workflowType, + job, + thereIsChunkOutsourced, + status, + openSplitModal, + openMergeModal, + isSplit, +}) => { + return ( +
+
+
+ + {job.source} + + + + {job.target} + +
+
ID: {job.id}
+
+
+
+ {countUnit === UNIT_COUNT.WORDS + ? 'Total word count' + : 'Total character count'} +
+ {workflowType === ANALYSIS_WORKFLOW_TYPES.STANDARD && ( +
+ Industry weighted + +
+ +
+
+
+ )} +
Matecat weighted
+
+
+ {!config.jobAnalysis && config.splitEnabled ? ( + !isSplit ? ( + + ) : ( + + ) + ) : null} +
+
+ ) +} + +export default CompareTableHeader diff --git a/public/js/components/analyze/JobAnalyze.js b/public/js/components/analyze/JobAnalyze.js index 7c5900431d..6e3088cb99 100644 --- a/public/js/components/analyze/JobAnalyze.js +++ b/public/js/components/analyze/JobAnalyze.js @@ -1,25 +1,49 @@ -import React from 'react' +import React, {useCallback, useEffect, useRef} from 'react' import {map} from 'lodash/collection' import $ from 'jquery' import JobAnalyzeHeader from './JobAnalyzeHeader' import JobTableHeader from './JobTableHeader' import ChunkAnalyze from './ChunkAnalyze' -class JobAnalyze extends React.Component { - constructor(props) { - super(props) - this.showDetails = this.showDetails.bind(this) - setTimeout(() => this.showDetails()) - } +const JobAnalyze = ({chunks, jobInfo, project, idJob, status, jobToScroll}) => { + const containerRef = useRef(null) - getChunks() { - if (this.props.chunks) { - return map(this.props.jobInfo.chunks, (item, index) => { - let chunk = this.props.chunks.find( - (c) => c.get('password') === item.password, - ) + const scrollElement = useCallback(() => { + const itemComponent = containerRef.current + if (itemComponent) { + $('#analyze-container').animate( + { + scrollTop: $(itemComponent).offset().top - 200, + }, + 500, + ) + } else { + setTimeout(() => scrollElement(), 500) + } + }, []) + + const showDetails = useCallback(() => { + if (jobToScroll === idJob) { + scrollElement() + } + }, [jobToScroll, idJob, scrollElement]) + + useEffect(() => { + const timer = setTimeout(() => showDetails()) + return () => clearTimeout(timer) + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []) + + useEffect(() => { + showDetails() + }, [jobToScroll, showDetails]) + + const getChunks = () => { + if (chunks) { + return map(jobInfo.chunks, (item, index) => { + let chunk = chunks.find((c) => c.get('password') === item.password) index++ - let job = this.props.project.get('jobs').find(function (jobElem) { + let job = project.get('jobs').find(function (jobElem) { return jobElem.get('password') === item.password }) @@ -28,15 +52,13 @@ class JobAnalyze extends React.Component { key={item.password} files={chunk.get('files').toJS()} job={job} - project={this.props.project} + project={project} total={item.summary} index={index} chunkInfo={item} - chunksSize={this.props.jobInfo.chunks.length} - rates={this.props.jobInfo.payable_rates} - workflowType={this.props.project - .get('analysis') - .get('workflow_type')} + chunksSize={jobInfo.chunks.length} + rates={jobInfo.payable_rates} + workflowType={project.get('analysis').get('workflow_type')} /> ) }) @@ -44,79 +66,23 @@ class JobAnalyze extends React.Component { return '' } - showDetails() { - if (this.props.jobToScroll == this.props.idJob && this.props.showAnalysis) { - this.scrollElement() - } - } + const iceMTRawWords = jobInfo.chunks.reduce((total, item) => { + const iceMT = item.summary.find((t) => t.type === 'ice_mt') + if (iceMT) return total + iceMT.raw + else return total + }, 0) - scrollElement() { - let itemComponent = this.container - let self = this - if (itemComponent) { - this.container.classList.add('show-details') - $('#analyze-container').animate( - { - scrollTop: $(itemComponent).offset().top - 200, - }, - 500, - ) - - // ReactDOM.findDOMNode(itemComponent).scrollIntoView({block: 'end'}); - setTimeout(function () { - self.container && self.container.classList.remove('show-details') - }, 1000) - } else { - setTimeout(function () { - self.scrollElement() - }, 500) - } - } - - shouldComponentUpdate() { - return true - } - - componentDidUpdate(prevProps) { - if (prevProps.jobToScroll !== this.props.jobToScroll) { - this.showDetails() - } - } - render() { - const iceMTRawWords = this.props.jobInfo.chunks.reduce((total, item) => { - const iceMT = item.summary.find((t) => t.type === 'ice_mt') - if (iceMT) return total + iceMT.raw - else total - }, 0) - return ( -
-
-
-
-
(this.container = container)} - > - - -
{this.getChunks()}
-
-
-
-
-
- ) - } + return ( +
+ + +
{getChunks()}
+
+ ) } export default JobAnalyze diff --git a/public/js/components/analyze/JobAnalyzeHeader.js b/public/js/components/analyze/JobAnalyzeHeader.js index 3a2c28b43f..0198b503fa 100644 --- a/public/js/components/analyze/JobAnalyzeHeader.js +++ b/public/js/components/analyze/JobAnalyzeHeader.js @@ -6,17 +6,13 @@ const JobAnalyzeHeader = ({jobInfo}) => { const totalWeighted = jobInfo.total_equivalent return (
-
-
- ID: {jobInfo.id} -
-
- {jobInfo.source_name} - - {jobInfo.target_name} -
+
ID: {jobInfo.id}
+
+ {jobInfo.source} + + {jobInfo.target}
-
+
{parseInt(totalWeighted)} {jobInfo.count_unit === UNIT_COUNT.WORDS diff --git a/public/js/components/analyze/OutsourceButton.js b/public/js/components/analyze/OutsourceButton.js new file mode 100644 index 0000000000..aba2f43888 --- /dev/null +++ b/public/js/components/analyze/OutsourceButton.js @@ -0,0 +1,51 @@ +import React, {createRef, useRef} from 'react' +import {ANALYSIS_STATUS} from '../../constants/Constants' +import TranslatedIcon from '../../../img/icons/TranslatedIcon' +import Tooltip from '../common/Tooltip' +import {Button, BUTTON_MODE, BUTTON_SIZE} from '../common/Button/Button' + +const OutsourceButton = ({chunk, index, openOutsourceModal, status}) => { + return !chunk.outsource_available && + chunk.outsource_info?.custom_payable_rate ? ( +
+ + Jobs created with custom billing models cannot be outsourced to + Translated. +
+ In order to outsource this job to Translated, please recreate it + using Matecat's standard billing model +
+ } + > + + +
+ ) : ( + + ) +} + +export default OutsourceButton diff --git a/public/js/components/analyze/ProjectAnalyze.js b/public/js/components/analyze/ProjectAnalyze.js index 5e0f162a9e..e9bb450de7 100644 --- a/public/js/components/analyze/ProjectAnalyze.js +++ b/public/js/components/analyze/ProjectAnalyze.js @@ -1,52 +1,40 @@ -import React from 'react' -import {isUndefined} from 'lodash' +import React, {memo} from 'react' import JobAnalyze from './JobAnalyze' -class ProjectAnalyze extends React.Component { - constructor(props) { - super(props) - } - - getJobs() { - let idArray = [] - return this.props.project.get('jobs').map((job) => { - const jobInfo = this.props.volumeAnalysis.find( - (item) => item.get('id') === job.get('id'), - ) - if ( - idArray.indexOf(job.get('id')) < 0 && - this.props.volumeAnalysis && - jobInfo - ) { - idArray.push(job.get('id')) - return ( - +const ProjectAnalyze = memo( + ({project, volumeAnalysis, status, jobToScroll}) => { + const getJobs = () => { + const idArray = [] + return project.get('jobs').map((job) => { + const jobInfo = volumeAnalysis.find( + (item) => item.get('id') === job.get('id'), ) - } - }) - } + if (idArray.indexOf(job.get('id')) < 0 && volumeAnalysis && jobInfo) { + idArray.push(job.get('id')) + return ( + + ) + } + }) + } - shouldComponentUpdate(nextProps) { - return ( - !nextProps.volumeAnalysis.equals(this.props.volumeAnalysis) || - nextProps.status !== this.props.status || - nextProps.jobToScroll !== this.props.jobToScroll - ) - } + return getJobs() + }, + (prevProps, nextProps) => + nextProps.volumeAnalysis.equals(prevProps.volumeAnalysis) && + nextProps.status === prevProps.status && + nextProps.jobToScroll === prevProps.jobToScroll, +) - render() { - return
{this.getJobs()}
- } -} +ProjectAnalyze.displayName = 'ProjectAnalyze' export default ProjectAnalyze diff --git a/public/js/components/analyze/SingleChunkJob.js b/public/js/components/analyze/SingleChunkJob.js new file mode 100644 index 0000000000..5528343ac9 --- /dev/null +++ b/public/js/components/analyze/SingleChunkJob.js @@ -0,0 +1,135 @@ +import React from 'react' +import OutsourceContainer from '../outsource/OutsourceContainer' +import { + ANALYSIS_STATUS, + ANALYSIS_WORKFLOW_TYPES, +} from '../../constants/Constants' +import { + Button, + BUTTON_MODE, + BUTTON_SIZE, + BUTTON_TYPE, +} from '../common/Button/Button' +import OutsourceButton from './OutsourceButton' +import CopyIcon from '../../../img/icons/CopyIcon' +import {Popup} from 'semantic-ui-react' + +const SingleChunkJob = ({ + job, + project, + status, + openOutsource, + outsourceJobId, + showDetails, + copyJobLinkToClipboard, + checkPayableChanged, + getDirectOpenButton, + closeOutsourceModal, + handleOpenOutsourceModal, + jobLinkRef, + containers, +}) => { + const workflowType = project.get('analysis').get('workflow_type') + const rawChunk = job.chunks[0] + const chunkAnalysis = { + ...rawChunk, + id: job.id, + outsource_available: job.outsource_available, + outsource: job.outsource, + target_name: job.target_name, + source_name: job.source_name, + } + + const totalRaw = chunkAnalysis.total_raw + const totalStandard = chunkAnalysis.total_industry || 0 + const chunkJob = project + .get('jobs') + .find( + (item) => + item.get('id') === chunkAnalysis.id && + item.get('password') === chunkAnalysis.password, + ) + + const isOutsourceOpen = openOutsource && outsourceJobId === job.id + + checkPayableChanged(job.id, chunkAnalysis.total_equivalent) + + return ( + <> +
+
+
+ (jobLinkRef.current[job.id] = el)} + onClick={(e) => e.stopPropagation()} + /> + + + + } + /> +
+
+
+
+
{totalRaw}
+
+ {workflowType === ANALYSIS_WORKFLOW_TYPES.STANDARD && ( +
+
{totalStandard}
+
+ )} +
(containers.current[job.id] = container)}> +
{chunkAnalysis.total_equivalent}
+
+
+
+ {!config.jobAnalysis && status === ANALYSIS_STATUS.DONE && ( + + )} + + {getDirectOpenButton(chunkAnalysis)} +
+
+ + + ) +} + +export default SingleChunkJob diff --git a/public/js/components/analyze/SplitChunkJob.js b/public/js/components/analyze/SplitChunkJob.js new file mode 100644 index 0000000000..e3ea761f5f --- /dev/null +++ b/public/js/components/analyze/SplitChunkJob.js @@ -0,0 +1,143 @@ +import React from 'react' +import {Popup} from 'semantic-ui-react' +import OutsourceContainer from '../outsource/OutsourceContainer' +import { + ANALYSIS_STATUS, + ANALYSIS_WORKFLOW_TYPES, +} from '../../constants/Constants' +import { + Button, + BUTTON_MODE, + BUTTON_SIZE, + BUTTON_TYPE, +} from '../common/Button/Button' +import OutsourceButton from './OutsourceButton' +import CopyIcon from '../../../img/icons/CopyIcon' + +const SplitChunkJob = ({ + job, + project, + status, + openOutsource, + outsourceJobId, + showDetails, + checkPayableChanged, + copyJobLinkToClipboard, + getDirectOpenButton, + closeOutsourceModal, + handleOpenOutsourceModal, + jobLinkRef, + containers, +}) => { + const workflowType = project.get('analysis').get('workflow_type') + + const chunksHtml = job.chunks.map((rawChunk, rawIndex) => { + const index = rawIndex + 1 + const chunkAnalysis = { + ...rawChunk, + id: job.id, + outsource_available: job.outsource_available, + target_name: job.target_name, + source_name: job.source_name, + } + + const isOutsourceOpen = + openOutsource && outsourceJobId === `${job.id}-${index}` + const chunkJob = project + .get('jobs') + .find( + (item) => + item.get('id') === chunkAnalysis.id && + item.get('password') === chunkAnalysis.password, + ) + checkPayableChanged(job.id + index, chunkAnalysis.total_equivalent) + + const jidChunk = `${chunkAnalysis.id}-${index}` + + return ( + <> +
+
+
{`Chunk ${index}`}
+
+ (jobLinkRef.current[jidChunk] = el)} + type="text" + readOnly + value={encodeURI(chunkAnalysis.urls.t)} + onClick={(e) => e.stopPropagation()} + /> + + + + } + /> +
+
+
+
+
{chunkAnalysis.total_raw}
+
+ {workflowType === ANALYSIS_WORKFLOW_TYPES.STANDARD && ( +
+
{chunkAnalysis.total_industry}
+
+ )} +
+ (containers.current[chunkAnalysis.id + index] = container) + } + > +
{chunkAnalysis.total_equivalent}
+
+
+
+ {!config.jobAnalysis && status === ANALYSIS_STATUS.DONE && ( + + )} + + {getDirectOpenButton(chunkAnalysis, `${job.id}-${index}`)} +
+
+ + + ) + }) + + return chunksHtml +} + +export default SplitChunkJob diff --git a/public/js/components/common/Badge/Badge.js b/public/js/components/common/Badge/Badge.js index 4803108a06..0e76c5092c 100644 --- a/public/js/components/common/Badge/Badge.js +++ b/public/js/components/common/Badge/Badge.js @@ -8,6 +8,9 @@ export const BADGE_TYPE = { YELLOW: 'yellow', BLUE: 'blue', RED: 'red', + PURPLE: 'purple', + ORANGE: 'orange', + GREY: 'grey', } export const BADGE_MODE = { DEFAULT: 'default', diff --git a/public/js/components/common/Button/Button.js b/public/js/components/common/Button/Button.js index 2d798fb739..8071b4bdea 100644 --- a/public/js/components/common/Button/Button.js +++ b/public/js/components/common/Button/Button.js @@ -26,19 +26,24 @@ export const BUTTON_TYPE = { SUCCESS: 'success', WARNING: 'warning', CRITICAL: 'critical', + PURPLE: 'purple', + ICON: 'icon', } export const BUTTON_MODE = { BASIC: 'basic', OUTLINE: 'outline', GHOST: 'ghost', LINK: 'link', + OUTLINE_BG: 'outlineBg', } export const BUTTON_SIZE = { SMALL: 'small', STANDARD: 'standard', MEDIUM: 'medium', BIG: 'big', + ICON_XSMALL: 'iconXSmall', ICON_SMALL: 'iconSmall', + ICON_MEDIUM: 'iconMedium', ICON_STANDARD: 'iconStandard', ICON_BIG: 'iconBig', LINK_SMALL: 'linkSmall', @@ -114,9 +119,9 @@ export const Button = React.forwardRef( {/* {value == CHECKBOX_STATE.CHECKED ? ( ) : value === CHECKBOX_STATE.INDETERMINATE ? ( ) : ( diff --git a/public/js/components/common/DropdownMenu/DropdownMenu.js b/public/js/components/common/DropdownMenu/DropdownMenu.js index ba45596f1f..d21855b5d2 100644 --- a/public/js/components/common/DropdownMenu/DropdownMenu.js +++ b/public/js/components/common/DropdownMenu/DropdownMenu.js @@ -42,7 +42,7 @@ export const DropdownMenu = ({ const defaultToggleButtonProps = { type: BUTTON_TYPE.DEFAULT, mode: BUTTON_MODE.GHOST, - size: BUTTON_SIZE.ICON_SMALL, + size: BUTTON_SIZE.ICON_XSMALL, children: , ...toggleButtonProps, className: `${toggleButtonProps.className || ''} ${className}`, @@ -134,7 +134,7 @@ export const DropdownMenu = ({ e.preventDefault() e.stopPropagation() } else { - item.onClick() + item.onClick(e) } setOpen(false) }} diff --git a/public/js/components/common/Input/Input.js b/public/js/components/common/Input/Input.js index 58e791daef..480403faa7 100644 --- a/public/js/components/common/Input/Input.js +++ b/public/js/components/common/Input/Input.js @@ -79,7 +79,7 @@ export const Input = React.forwardRef( {type === INPUT_TYPE.PASSWORD && ( - )} - -
- {itemsCoords && ( - -
- {children.map((item) => item)} -
-
- )} -
- ) -} - -const MenuButtonItemType = PropTypes.shape({ - type: PropTypes.oneOf([MenuButtonItem]), -}) - -MenuButton.propTypes = { - label: PropTypes.string, - icon: PropTypes.node, - onClick: PropTypes.func, - className: PropTypes.string, - itemsTarget: PropTypes.object, - children: PropTypes.arrayOf(MenuButtonItemType), - disabled: PropTypes.bool, - isVisibleRectArrow: PropTypes.bool, -} diff --git a/public/js/components/common/MenuButton/MenuButtonItem.js b/public/js/components/common/MenuButton/MenuButtonItem.js deleted file mode 100644 index 7e32592e12..0000000000 --- a/public/js/components/common/MenuButton/MenuButtonItem.js +++ /dev/null @@ -1,12 +0,0 @@ -import React from 'react' - -export const MenuButtonItem = ({children, className, ...restProps}) => { - return ( - - ) -} diff --git a/public/js/components/common/MenuButton/index.js b/public/js/components/common/MenuButton/index.js deleted file mode 100644 index 6ddeec49b2..0000000000 --- a/public/js/components/common/MenuButton/index.js +++ /dev/null @@ -1 +0,0 @@ -export * from './MenuButton' diff --git a/public/js/components/common/NumericStepper/NumericStepper.js b/public/js/components/common/NumericStepper/NumericStepper.js index 758e1f57ba..9caba3e857 100644 --- a/public/js/components/common/NumericStepper/NumericStepper.js +++ b/public/js/components/common/NumericStepper/NumericStepper.js @@ -78,14 +78,14 @@ export const NumericStepper = ({ />
)} -
+
{ + if (closeOnClickInside) setIsOpen(false) + }} + > {children}
{(cancelButtonProps || confirmButtonProps) && ( @@ -153,4 +163,6 @@ Popover.propTypes = { verticalAlign: PropTypes.oneOf([...Object.values(POPOVER_VERTICAL_ALIGN)]), onClose: PropTypes.func, children: PropTypes.node, + forceOpenMenu: PropTypes.bool, + closeOnClickInside: PropTypes.bool, } diff --git a/public/js/components/common/Select.js b/public/js/components/common/Select.js index eb1b6abc77..3ab2d51e95 100644 --- a/public/js/components/common/Select.js +++ b/public/js/components/common/Select.js @@ -355,7 +355,7 @@ export const Select = ({
) : undefined} - {renderSelection()} + {renderSelection()}
{ + return ( +
+ {label ?? 'Loading'} +
+ ) +} + +SpinnerLoader.propTypes = { + label: PropTypes.string, + size: PropTypes.oneOf(Object.values(SPINNER_LOADER_SIZE)), + className: PropTypes.string, +} diff --git a/public/js/components/common/VirtualList/Rows/RowSegment.js b/public/js/components/common/VirtualList/Rows/RowSegment.js index b5bf04b237..dba396b3ae 100644 --- a/public/js/components/common/VirtualList/Rows/RowSegment.js +++ b/public/js/components/common/VirtualList/Rows/RowSegment.js @@ -91,10 +91,8 @@ function RowSegment({
{file ? (
- + {CommonUtils.getFileIcon(fileType[0])} + {file.file_name}
diff --git a/public/js/components/createProject/HomePageSection.js b/public/js/components/createProject/HomePageSection.js index fbee9eca17..f4ee682bc2 100644 --- a/public/js/components/createProject/HomePageSection.js +++ b/public/js/components/createProject/HomePageSection.js @@ -3,7 +3,7 @@ import {Button, BUTTON_SIZE, BUTTON_TYPE} from '../common/Button/Button' export const HomePageSection = () => { return (
-
+

Why Choose Us

diff --git a/public/js/components/createProject/UploadFileLocal.js b/public/js/components/createProject/UploadFileLocal.js index 1e906c0ce6..fb156ac15f 100644 --- a/public/js/components/createProject/UploadFileLocal.js +++ b/public/js/components/createProject/UploadFileLocal.js @@ -138,7 +138,7 @@ function FileItem({file: f, onDelete}) { return (
- + {CommonUtils.getFileIcon(f.ext)} {f.name}
{f.error && ( diff --git a/public/js/components/createProject/UploadFileLocal.test.js b/public/js/components/createProject/UploadFileLocal.test.js index 3663fcb4e3..1390d017e2 100644 --- a/public/js/components/createProject/UploadFileLocal.test.js +++ b/public/js/components/createProject/UploadFileLocal.test.js @@ -29,7 +29,7 @@ jest.mock('../../actions/CreateProjectActions', () => ({ })) jest.mock('../../utils/commonUtils', () => ({ - getIconClass: jest.fn(() => 'extdoc'), + getFileIcon: jest.fn(() => null), dispatchCustomEvent: jest.fn(), })) diff --git a/public/js/components/createProject/UploadGdrive.js b/public/js/components/createProject/UploadGdrive.js index 4633febfdb..6128321a16 100644 --- a/public/js/components/createProject/UploadGdrive.js +++ b/public/js/components/createProject/UploadGdrive.js @@ -9,6 +9,7 @@ import {CreateProjectContext} from './CreateProjectContext' import DriveIcon from '../../../img/icons/DriveIcon' import {useGDrivePicker} from './hooks/useGDrivePicker' import {useGDriveFiles} from './hooks/useGDriveFiles' +import {SpinnerLoader} from '../common/SpinnerLoader' export const UploadGdrive = () => { const { @@ -96,9 +97,7 @@ export const UploadGdrive = () => { function LoadingOverlay() { return (
-
-
Uploading Files
-
+
) } @@ -109,7 +108,7 @@ function GDriveFileList({files, onDelete}) { {files.map((f, idx) => (
- + {CommonUtils.getFileIcon(f.ext)} {f.name}
{getPrintableFileSize(f.size)}
diff --git a/public/js/components/createProject/UploadGdrive.test.js b/public/js/components/createProject/UploadGdrive.test.js index 67e0c7e48a..b5f1d44b59 100644 --- a/public/js/components/createProject/UploadGdrive.test.js +++ b/public/js/components/createProject/UploadGdrive.test.js @@ -38,7 +38,7 @@ jest.mock('../../stores/UserStore', () => ({ updateConnectedService: jest.fn(), })) jest.mock('../../utils/commonUtils', () => ({ - getIconClass: jest.fn(() => 'extdoc'), + getFileIcon: jest.fn(() => 'extdoc'), dispatchCustomEvent: jest.fn(), })) jest.mock('../../../img/icons/DriveIcon', () => { diff --git a/public/js/components/footer/CattoolFooter.js b/public/js/components/footer/CattoolFooter.js index 5b79afd246..773b925dfb 100644 --- a/public/js/components/footer/CattoolFooter.js +++ b/public/js/components/footer/CattoolFooter.js @@ -99,7 +99,7 @@ export const CattoolFooter = ({
) } diff --git a/public/js/components/header/Header.test.js b/public/js/components/header/Header.test.js index 50e6f5031c..929cf65a85 100644 --- a/public/js/components/header/Header.test.js +++ b/public/js/components/header/Header.test.js @@ -14,7 +14,7 @@ const modalElement = document.createElement('div') modalElement.id = 'modal' document.body.appendChild(modalElement) const mountPoint = createRoot(modalElement) -afterAll(() => mountPoint.unmount()) +afterAll(() => act(() => mountPoint.unmount())) window.config = { isLoggedIn: 1, diff --git a/public/js/components/header/TeamDropdown.js b/public/js/components/header/TeamDropdown.js index e66d82cc6b..07d746d10c 100644 --- a/public/js/components/header/TeamDropdown.js +++ b/public/js/components/header/TeamDropdown.js @@ -1,7 +1,7 @@ import React, {useCallback, useContext, useRef, useState} from 'react' import PropTypes from 'prop-types' import {ApplicationWrapperContext} from '../common/ApplicationWrapper/ApplicationWrapperContext' -import {BUTTON_TYPE, Button} from '../common/Button/Button' +import {BUTTON_SIZE, BUTTON_TYPE, Button} from '../common/Button/Button' import IconDown from '../icons/IconDown' import ManageActions from '../../actions/ManageActions' import UserActions from '../../actions/UserActions' @@ -80,6 +80,7 @@ export const TeamDropdown = ({isManage = true, showModals = true}) => { ref={triggerRef} className={`trigger-button${isDropdownVisible ? ' open' : ''}`} type={BUTTON_TYPE.DEFAULT} + size={BUTTON_SIZE.SMALL} onClick={toggleDropdown} > {selectedTeam?.name ?? 'Choose team'} diff --git a/public/js/components/header/UserMenu.js b/public/js/components/header/UserMenu.js index 7250f1323b..c0bfe9dbec 100644 --- a/public/js/components/header/UserMenu.js +++ b/public/js/components/header/UserMenu.js @@ -31,20 +31,21 @@ export const UserMenu = () => { return ( ) : (
@@ -54,6 +55,7 @@ export const UserMenu = () => { }} align={POPOVER_ALIGN.RIGHT} verticalAlign={POPOVER_VERTICAL_ALIGN.BOTTOM} + buttonContainerClassName={'user-menu-popover'} >
@@ -106,7 +108,6 @@ export const UserMenu = () => { diff --git a/public/js/components/header/cattol/CommentsButton.js b/public/js/components/header/cattol/CommentsButton.js index 54df706f27..66505452bc 100644 --- a/public/js/components/header/cattol/CommentsButton.js +++ b/public/js/components/header/cattol/CommentsButton.js @@ -8,6 +8,14 @@ import CatToolStore from '../../../stores/CatToolStore' import CattolConstants from '../../../constants/CatToolConstants' import SegmentActions from '../../../actions/SegmentActions' import {getTeamUsers} from '../../../api/getTeamUsers' +import {Popover, POPOVER_ALIGN} from '../../common/Popover/Popover' +import CommentsIcon from '../../../../img/icons/CommentsIcon' +import { + Button, + BUTTON_MODE, + BUTTON_SIZE, + BUTTON_TYPE, +} from '../../common/Button/Button' const commentsTypes = {sticky: 3, resolve: 2, comment: 1} export const CommentsButton = ({}) => { @@ -22,10 +30,6 @@ export const CommentsButton = ({}) => { CommentsActions.storeComments(resp.data.entries.comments, resp.data.user) }) } - const toggleComments = () => { - CatToolActions.closeSubHeader() - setShowComments(!showComments) - } const updateComments = () => { setComments(CommentsStore.db.history) } @@ -56,50 +60,46 @@ export const CommentsButton = ({}) => { setShowComments(false) } const renderComments = () => { - return CommentsStore.db.history.map((comment) => { - let message = comment.message - .replace(/\/r/g,
) - .replace(/\/n/g,
) - message = parseCommentHtml(message) - return ( -
-
- - Segment{' '} - - {comment.id_segment} + if (CommentsStore?.db?.history.length > 0) { + return CommentsStore?.db?.history?.map((comment) => { + let message = comment.message + .replace(/\/r/g,
) + .replace(/\/n/g,
) + message = parseCommentHtml(message) + return ( +
+
+ + Segment {comment.id_segment} - - - {comment.full_name} - -
- + {comment.full_name} +
+
+

-

-

-
- ) - }) + ) + }) + } else { + return
No comments
+ } } useEffect(() => { if (config.id_team) { @@ -140,61 +140,38 @@ export const CommentsButton = ({}) => { return ( <> {config.comments_enabled && ( -
-
- counterOpenComments + counterResolvedComments > 0 - ? toggleComments() - : null - } - > - - - -
- {counterResolvedComments > 0 && ( - - {counterResolvedComments} - - )} - {counterOpenComments > 0 && ( - {counterOpenComments} - )} -
-
- {showComments ? ( -
-
- {counterOpenComments + counterResolvedComments === 0 ? ( -
-
-
- No comments -
+ + + {counterResolvedComments > 0 && ( +
0 ? 'button-badge-left' : ''}`} + > + {counterResolvedComments}
-
- ) : ( -
- {renderComments()} -
- )} -
- ) : null} -
+ )} + {counterOpenComments > 0 && ( +
+ {counterOpenComments} +
+ )} + + ), + size: BUTTON_SIZE.ICON_STANDARD, + mode: BUTTON_MODE.GHOST, + type: BUTTON_TYPE.ICON, + disabled: counterOpenComments + counterResolvedComments === 0, + }} + disabled={counterOpenComments + counterResolvedComments === 0} + forceOpenMenu={showComments} + > +
{renderComments()}
+ )} ) diff --git a/public/js/components/header/cattol/DownloadMenu.js b/public/js/components/header/cattol/DownloadMenu.js index 280f8882b4..3079fbf842 100644 --- a/public/js/components/header/cattol/DownloadMenu.js +++ b/public/js/components/header/cattol/DownloadMenu.js @@ -7,6 +7,12 @@ import SegmentStore from '../../../stores/SegmentStore' import ModalsActions from '../../../actions/ModalsActions' import CatToolActions from '../../../actions/CatToolActions' import DownloadFileUtils from '../../../utils/downloadFileUtils' +import { + DROPDOWN_MENU_TRIGGER_MODE, + DropdownMenu, +} from '../../common/DropdownMenu/DropdownMenu' +import {BUTTON_MODE, BUTTON_SIZE, BUTTON_TYPE} from '../../common/Button/Button' +import Download from '../../../../img/icons/Download' export const DownloadMenu = ({password, jid, isGDriveProject}) => { const [downloadTranslationAvailable, setDownloadTranslationAvailable] = @@ -111,91 +117,102 @@ export const DownloadMenu = ({password, jid, isGDriveProject}) => { } }, []) return ( - + , + size: BUTTON_SIZE.ICON_STANDARD, + mode: downloadTranslationAvailable + ? BUTTON_MODE.BASIC + : BUTTON_MODE.GHOST, + type: downloadTranslationAvailable + ? BUTTON_TYPE.PRIMARY + : BUTTON_TYPE.ICON, + onClick: (e) => { + runDownload() + e.preventDefault() + }, + }} + className={downloadTranslationAvailable ? 'job-completed' : ''} + disabled={downloadDisabled} + items={[ + ...(downloadTranslationAvailable + ? [ + { + label: ( + <> + {' '} + + {isGDriveProject + ? 'Open in Google Drive' + : 'Download Translation'} + + ), + onClick: () => runDownload(), + }, + ] + : [ + { + label: ( + <> + + {isGDriveProject + ? 'Open preview in Google Drive' + : 'Download Draft'} + + ), + onClick: () => runDownload(), + }, + ]), + ...(!isGDriveProject + ? [ + { + label: ( + <> + + Download Original + + ), + onClick: () => { + window.open(`/api/v2/original/${jid}/${password}`, '_blank') + }, + }, + ] + : [ + { + label: ( + <> + + Open original in Google Drive + + ), + onClick: () => + continueDownloadWithGoogleDrive({originalFiles: 1}), + }, + ]), + { + label: ( + <> + + Export XLIFF + + ), + onClick: () => { + window.open(`/api/v2/xliff/${jid}/${password}/${jid}.zip`, '_blank') + }, + }, + { + label: ( + <> + + Export Job TMX + + ), + onClick: () => { + window.open(`/api/v2/tmx/${jid}/${password}`, '_blank') + }, + }, + ]} + /> ) } diff --git a/public/js/components/header/cattol/FilesMenu.js b/public/js/components/header/cattol/FilesMenu.js index e3ecf9b7c5..8223e2c5db 100644 --- a/public/js/components/header/cattol/FilesMenu.js +++ b/public/js/components/header/cattol/FilesMenu.js @@ -7,31 +7,20 @@ import SegmentActions from '../../../actions/SegmentActions' import SegmentStore from '../../../stores/SegmentStore' import {FilenameLabel} from '../../common/FilenameLabel' import {getFileSegments} from '../../../api/getFileSegments' - -function useOutsideAlerter(ref, fun) { - useEffect(() => { - function handleClickOutside(event) { - if (ref.current && !ref.current.contains(event.target)) { - fun() - } - } - // Bind the event listener - document.addEventListener('mousedown', handleClickOutside) - return () => { - // Unbind the event listener on clean up - document.removeEventListener('mousedown', handleClickOutside) - } - }, [ref]) -} +import { + DROPDOWN_SEPARATOR, + DropdownMenu, +} from '../../common/DropdownMenu/DropdownMenu' +import Files from '../../../../img/icons/Files' +import {BUTTON_MODE, BUTTON_SIZE} from '../../common/Button/Button' +import GoToIcon from '../../../../img/icons/GoToIcon' +import Check from '../../../../img/icons/Check' export const FilesMenu = ({projectName}) => { const [files, setFiles] = useState() const [currentFile, setCurrentFile] = useState() - const [menuVisible, setMenuVisible] = useState(false) const [currentSegment, setCurrentSegment] = useState() const firstJobSegment = useRef() - const containerRef = useRef() - useOutsideAlerter(containerRef, () => setMenuVisible(false)) useEffect(() => { getJobFileInfo(config.id_job, config.password).then((response) => { @@ -46,11 +35,11 @@ export const FilesMenu = ({projectName}) => { }) }, []) - const toggleMenu = () => { - if (!menuVisible) { + const toggleMenu = (open) => { + if (open) { CatToolActions.closeSubHeader() const current = SegmentStore.getCurrentSegment() - if (current) { + if (current && current.opened) { setCurrentSegment(current.sid) // check if use id_file or id_file_part const idFileProp = files.find( @@ -60,8 +49,9 @@ export const FilesMenu = ({projectName}) => { : 'id_file_part' setCurrentFile(parseInt(current[idFileProp])) } + } else { + setCurrentSegment() } - setMenuVisible(!menuVisible) } const goToCurrentSegment = () => { @@ -82,93 +72,64 @@ export const FilesMenu = ({projectName}) => { } } - return ( -
- {files && ( - <> -
- - {files.length} - - -
-
- - {projectName} - -
- - )} - {menuVisible && ( -
-
-
- Go to current segment + const getFilesMenu = () => { + return [ + { + label: ( + <> + +
Go to current segment
{Shortcuts.cattol.events.gotoCurrent.keystrokes[ Shortcuts.shortCutsKeyType ].toUpperCase()} -
-
- {/**/} - {/* Go to first segment of the file:*/} - {/**/} - {files.map((file) => { - return ( -
goToFirstSegment(file)} - className={`file-list-item ${ - currentFile === file.id ? 'current' : '' - }`} - title={`${file.file_name} - Click to go to the first segment`} - > - - {file.file_name} - {currentFile === file.id && ( - - - - - - )} -
- ) - })} -
-
- )} -
+ + ), + onClick: goToCurrentSegment, + disabled: !currentSegment, + }, + DROPDOWN_SEPARATOR, + ...files.map((file) => ({ + label: ( + <> +
+ {CommonUtils.getFileIcon( + file.file_name.split('.')[file.file_name.split('.').length - 1], + )} + {file.file_name} +
+ {currentFile === file.id && } + + ), + onClick: () => goToFirstSegment(file), + selected: currentFile === file.id, + })), + ] + } + + return ( + <> + + + + {projectName} + + + ), + size: BUTTON_SIZE.STANDARD, + mode: BUTTON_MODE.LINK, + className: 'files-menu-button', + }} + items={files && getFilesMenu()} + onOpenChange={toggleMenu} + className={'file-list-item'} + disabled={!files} + /> + ) } diff --git a/public/js/components/header/cattol/Header.js b/public/js/components/header/cattol/Header.js index d27d140a77..c8920b52a1 100644 --- a/public/js/components/header/cattol/Header.js +++ b/public/js/components/header/cattol/Header.js @@ -10,10 +10,16 @@ import {SegmentsQAButton} from './SegmetsQAButton' import {SearchButton} from './SearchButton' import {CommentsButton} from './CommentsButton' import {SegmentsFilterButton} from './SegmentsFilterButton' -import {SettingsButton} from './SettingsButton' import {ActionMenu} from '../ActionMenu' import {UserMenu} from '../UserMenu' import {ApplicationWrapperContext} from '../../common/ApplicationWrapper/ApplicationWrapperContext' +import { + Button, + BUTTON_MODE, + BUTTON_SIZE, + BUTTON_TYPE, +} from '../../common/Button/Button' +import SettingsIcon from '../../../../img/icons/SettingsIcon' export const Header = ({ jid, @@ -27,7 +33,6 @@ export const Header = ({ projectCompletionEnabled, isReview, secondRevisionsCount, - overallQualityClass, qualityReportHref, allowLinkToAnalysis, analysisEnabled, @@ -80,30 +85,35 @@ export const Header = ({ jid={jid} isGDriveProject={isGDriveProject} /> + {/*Search*/} + + + {/*Segments filter*/} + + + {/*Comments*/} + + + {/*Segments Issues*/} + {/*Quality Report*/} - {/*Segments Issues*/} - - - {/*Search*/} - - - {/*Comments*/} - - - {/*Segments filter*/} - - {/*Settings Icon*/} - + {/*Dropdown menu*/} { const [files, setFiles] = useState() @@ -51,11 +56,11 @@ export const JobMetadata = ({metadata}) => { } }, [metadata]) - useEffect(() => { - // if (showButton && !closedPopupStorage) { - // showInfoTooltipFunction() - // } - }, [showButton]) + // useEffect(() => { + // // if (showButton && !closedPopupStorage) { + // // showInfoTooltipFunction() + // // } + // }, [showButton]) useEffect(() => { const updateFiles = (files) => { @@ -79,32 +84,14 @@ export const JobMetadata = ({metadata}) => { return ( showButton && ( -
-
- - - - -
-
+ + ) ) } diff --git a/public/js/components/header/cattol/MarkAsCompleteButton.js b/public/js/components/header/cattol/MarkAsCompleteButton.js index 89d39ce40b..bb694a4088 100644 --- a/public/js/components/header/cattol/MarkAsCompleteButton.js +++ b/public/js/components/header/cattol/MarkAsCompleteButton.js @@ -9,8 +9,9 @@ import CattolConstants from '../../../constants/CatToolConstants' import CatToolActions from '../../../actions/CatToolActions' import {deleteCompletionEvents} from '../../../api/deleteCompletionEvents' import ModalsActions from '../../../actions/ModalsActions' +import {Button, BUTTON_MODE, BUTTON_TYPE} from '../../common/Button/Button' +import Check from '../../../../img/icons/Check' export const MarkAsCompleteButton = ({featureEnabled, isReview}) => { - const button = useRef() const [markedAsComplete, setMarkedAsComplete] = useState( config.job_marked_complete, ) @@ -207,19 +208,14 @@ export const MarkAsCompleteButton = ({featureEnabled, isReview}) => { <> {/*Mark as complete*/} {featureEnabled && ( - )} ) diff --git a/public/js/components/header/cattol/QAComponent.js b/public/js/components/header/cattol/QAComponent.js index ce1131c94f..f795ce40c6 100644 --- a/public/js/components/header/cattol/QAComponent.js +++ b/public/js/components/header/cattol/QAComponent.js @@ -6,6 +6,15 @@ import SegmentStore from '../../../stores/SegmentStore' import SegmentConstants from '../../../constants/SegmentConstants' import SegmentQA from '../../../../img/icons/SegmentQA' import AlertIcon from '../../../../img/icons/AlertIcon' +import { + Button, + BUTTON_MODE, + BUTTON_SIZE, + BUTTON_TYPE, +} from '../../common/Button/Button' +import InfoIcon from '../../../../img/icons/InfoIcon' +import ChevronLeft from '../../../../img/icons/ChevronLeft' +import ChevronRight from '../../../../img/icons/ChevronRight' class QAComponent extends React.Component { constructor(props) { @@ -132,9 +141,11 @@ class QAComponent extends React.Component { ? ' mc-bg-gray' : '' error.push( - , + , ) } else { let activeClass = @@ -154,9 +165,11 @@ class QAComponent extends React.Component { ? ' mc-bg-gray' : '' error.push( - , + , ) } } @@ -184,9 +197,11 @@ class QAComponent extends React.Component { : '' if (key === 'TAGS') { warning.push( - , + , ) } else if (key !== 'MISMATCH') { warning.push( - , + , ) } else { mismatch = ( - + ) } } @@ -260,9 +279,11 @@ class QAComponent extends React.Component { ? ' mc-bg-gray' : '' info.push( - , + , ) } }) } } let segmentsWithActive = - error.length > 0 || warning.length > 0 || info.length > 0 ? true : false + error.length > 0 || warning.length > 0 || info.length > 0 return this.props.active && this.state.totalWarnings > 0 ? (
@@ -291,7 +313,7 @@ class QAComponent extends React.Component {
) : null} {segmentsWithActive ? ( -
+
{error} {warning} {info} @@ -333,7 +355,7 @@ class QAComponent extends React.Component { ) : null} {mismatch ? (
-
{mismatch}
+
{mismatch}
) : null}
@@ -341,24 +363,24 @@ class QAComponent extends React.Component {
- + +
{this.state.navigationIndex + 1} /{' '} {this.state.navigationList.length} {/*Segments*/}
- + +
diff --git a/public/js/components/header/cattol/SearchButton.js b/public/js/components/header/cattol/SearchButton.js index 95b10de5e4..db5dc1017c 100644 --- a/public/js/components/header/cattol/SearchButton.js +++ b/public/js/components/header/cattol/SearchButton.js @@ -1,9 +1,15 @@ -import React from 'react' +import React, {useEffect, useState} from 'react' import SearchUtils from './search/searchUtils' import {useHotkeys} from 'react-hotkeys-hook' import {Shortcuts} from '../../../utils/shortcuts' +import {Button, BUTTON_MODE, BUTTON_SIZE} from '../../common/Button/Button' +import Search from '../../../../img/icons/Search' +import CatToolStore from '../../../stores/CatToolStore' +import CatToolConstants from '../../../constants/CatToolConstants' +import SearchFilled from '../../../../img/icons/SearchFilled' export const SearchButton = () => { + const [searchOpen, setSearchOpen] = useState(SearchUtils.searchOpen) useHotkeys( Shortcuts.cattol.events.openSearch.keystrokes[Shortcuts.shortCutsKeyType], (e) => openSearch(e), @@ -12,52 +18,44 @@ export const SearchButton = () => { const openSearch = (event) => { SearchUtils.toggleSearch(event) } + useEffect(() => { + const closeSearch = (container) => { + if (container && container === 'search') { + setSearchOpen((prevState) => !prevState) + } else { + setSearchOpen(false) + } + } + CatToolStore.addListener(CatToolConstants.TOGGLE_CONTAINER, closeSearch) + CatToolStore.addListener(CatToolConstants.CLOSE_SUBHEADER, closeSearch) + CatToolStore.addListener(CatToolConstants.SHOW_CONTAINER, closeSearch) + return () => { + CatToolStore.removeListener( + CatToolConstants.TOGGLE_CONTAINER, + closeSearch, + ) + CatToolStore.removeListener(CatToolConstants.CLOSE_SUBHEADER, closeSearch) + CatToolStore.removeListener(CatToolConstants.SHOW_CONTAINER, closeSearch) + } + }, []) return ( - <> - {SearchUtils.searchEnabled && ( - - )} - + SearchUtils.searchEnabled && + (searchOpen ? ( + + ) : ( + + )) ) } diff --git a/public/js/components/header/cattol/SegmentsFilterButton.js b/public/js/components/header/cattol/SegmentsFilterButton.js index 7bbbeb3e39..15e24422fb 100644 --- a/public/js/components/header/cattol/SegmentsFilterButton.js +++ b/public/js/components/header/cattol/SegmentsFilterButton.js @@ -1,7 +1,14 @@ -import React from 'react' +import React, {useEffect, useState} from 'react' import SegmentFilter from './segment_filter/segment_filter' +import {Button, BUTTON_MODE, BUTTON_SIZE} from '../../common/Button/Button' +import CatToolStore from '../../../stores/CatToolStore' +import CatToolConstants from '../../../constants/CatToolConstants' +import FilterFilledIcon from '../../../../img/icons/FilterFilledIcon' +import FilterIcon from '../../../../img/icons/FilterIcon' export const SegmentsFilterButton = () => { + const [filterOpen, setFilterOpen] = useState(SegmentFilter.open) + const openSegmetsFilters = (event) => { event.preventDefault() if (!SegmentFilter.open) { @@ -11,41 +18,46 @@ export const SegmentsFilterButton = () => { SegmentFilter.open = false } } + useEffect(() => { + const closeFilter = (container) => { + if (container && container === 'segmentFilter') { + setFilterOpen((prevState) => !prevState) + } else { + setFilterOpen(false) + } + } + CatToolStore.addListener(CatToolConstants.TOGGLE_CONTAINER, closeFilter) + CatToolStore.addListener(CatToolConstants.CLOSE_SUBHEADER, closeFilter) + CatToolStore.addListener(CatToolConstants.SHOW_CONTAINER, closeFilter) + return () => { + CatToolStore.removeListener( + CatToolConstants.TOGGLE_CONTAINER, + closeFilter, + ) + CatToolStore.removeListener(CatToolConstants.CLOSE_SUBHEADER, closeFilter) + CatToolStore.removeListener(CatToolConstants.SHOW_CONTAINER, closeFilter) + } + }, []) return ( <> - {config.segmentFilterEnabled && ( -
- + + + ) : ( + -
- )} + + + ))} ) } diff --git a/public/js/components/header/cattol/SegmetsQAButton.js b/public/js/components/header/cattol/SegmetsQAButton.js index 2bc71e74e3..db8306c119 100644 --- a/public/js/components/header/cattol/SegmetsQAButton.js +++ b/public/js/components/header/cattol/SegmetsQAButton.js @@ -2,11 +2,26 @@ import React, {useEffect, useState} from 'react' import CatToolActions from '../../../actions/CatToolActions' import SegmentStore from '../../../stores/SegmentStore' import SegmentConstants from '../../../constants/SegmentConstants' +import { + Button, + BUTTON_MODE, + BUTTON_SIZE, + BUTTON_TYPE, +} from '../../common/Button/Button' +import AlertIcon from '../../../../img/icons/AlertIcon' +import CatToolStore from '../../../stores/CatToolStore' +import CatToolConstants from '../../../constants/CatToolConstants' +import SearchUtils from './search/searchUtils' +import AlertIconFull from '../../../../img/icons/AlertIconFull' +import QAICon from '../../../../img/icons/QAICon' +import QAFilledIcon from '../../../../img/icons/QAFilledICon' export const SegmentsQAButton = () => { const [warnings, setWarnings] = useState() const [totalIssues, setTotalIssues] = useState(0) const [numberClass, setNumberClass] = useState('') + const [qaOpen, setQaOpen] = useState(SearchUtils.searchOpen) + const openQA = (event) => { event.preventDefault() CatToolActions.toggleQaIssues() @@ -18,11 +33,11 @@ export const SegmentsQAButton = () => { setWarnings(warnings) const iconClass = warnings.matecat.ERROR.total && warnings.matecat.ERROR.total > 0 - ? '' + ? 'error' : warnings.matecat.WARNING.total && warnings.matecat.WARNING.total > 0 - ? 'numberwarning' + ? 'warning' : warnings.matecat.INFO.total && warnings.matecat.INFO.total > 0 - ? 'numberinfo' + ? 'info' : '' setNumberClass(iconClass) } @@ -30,53 +45,48 @@ export const SegmentsQAButton = () => { SegmentConstants.UPDATE_GLOBAL_WARNINGS, updateWarnings, ) + const closeQA = (container) => { + if (container && container === 'qaComponent') { + setQaOpen((prevState) => !prevState) + } else { + setQaOpen(false) + } + } + CatToolStore.addListener(CatToolConstants.TOGGLE_CONTAINER, closeQA) + CatToolStore.addListener(CatToolConstants.CLOSE_SUBHEADER, closeQA) + CatToolStore.addListener(CatToolConstants.SHOW_CONTAINER, closeQA) return () => { SegmentStore.removeListener( SegmentConstants.UPDATE_GLOBAL_WARNINGS, updateWarnings, ) + CatToolStore.removeListener(CatToolConstants.TOGGLE_CONTAINER, closeQA) + CatToolStore.removeListener(CatToolConstants.CLOSE_SUBHEADER, closeQA) + CatToolStore.removeListener(CatToolConstants.SHOW_CONTAINER, closeQA) } }, []) return ( -
0 ? 'Click to see the segments with potential issues' : 'Well done, no errors found!' } + tooltipPosition="bottom" + disabled={!totalIssues} + onClick={openQA} + className={'qaButton'} > - - {warnings && totalIssues > 0 && ( - {totalIssues} - )} - - - - - - - -
+ {qaOpen ? : } + {warnings && totalIssues > 0 && ( +
+ {totalIssues} +
+ )} + ) } diff --git a/public/js/components/header/cattol/SettingsButton.js b/public/js/components/header/cattol/SettingsButton.js deleted file mode 100644 index e3ab694d27..0000000000 --- a/public/js/components/header/cattol/SettingsButton.js +++ /dev/null @@ -1,29 +0,0 @@ -import React from 'react' -import {Shortcuts} from '../../../utils/shortcuts' - -export const SettingsButton = ({openTmPanel}) => { - return ( -
- - - -
- ) -} diff --git a/public/js/components/header/cattol/search/Search.js b/public/js/components/header/cattol/search/Search.js index f454e774fc..c718ec3c33 100644 --- a/public/js/components/header/cattol/search/Search.js +++ b/public/js/components/header/cattol/search/Search.js @@ -23,6 +23,9 @@ import { } from '../../../../constants/Constants' import {Select} from '../../../common/Select' import {segmentTranslation} from '../../../../setTranslationUtil' +import {Button, BUTTON_MODE, BUTTON_SIZE} from '../../../common/Button/Button' +import ChevronLeft from '../../../../../img/icons/ChevronLeft' +import ChevronRight from '../../../../../img/icons/ChevronRight' class Search extends React.Component { constructor(props) { @@ -370,9 +373,7 @@ class Search extends React.Component { }) } } - $('body').addClass('search-open') } else { - $('body').removeClass('search-open') if (!this.state.focus) { this.setState({ focus: true, @@ -497,21 +498,22 @@ class Search extends React.Component { {this.state.searchResults.length > 0 ? (

{segmentIndex + 1 + ' of ' + totalResults + ' segments'}

- - - + + +
) : null}
@@ -623,8 +625,7 @@ class Search extends React.Component { ) { findIsDisabled = false } - let findButtonClassDisabled = - !this.state.funcFindButton || findIsDisabled ? 'disabled' : '' + let findButtonDisabled = !this.state.funcFindButton || findIsDisabled let statusDropdownClass = this.state.search.selectStatus !== '' && this.state.search.selectStatus !== 'all' @@ -636,17 +637,15 @@ class Search extends React.Component { ? '' : 'disabled' let replaceCheckboxClass = this.state.search.searchTarget ? '' : 'disabled' - let replaceButtonsClass = + let replaceDisabled = !( this.state.search.enableReplace && this.state.search.searchTarget && !this.state.funcFindButton && !this.state.isSelectedTag - ? '' - : 'disabled' - let replaceAllButtonsClass = + ) + let replaceAllDisabled = !( this.state.search.enableReplace && this.state.search.searchTarget - ? '' - : 'disabled' + ) let clearVisible = this.state.search.searchTarget !== '' || this.state.search.searchSource !== '' || @@ -804,28 +803,27 @@ class Search extends React.Component { {this.state.showReplaceOptionsInSearch ? (
- - - +
{this.jobIsSplitted && (
@@ -844,15 +842,13 @@ class Search extends React.Component {
) : (
- +
)}
diff --git a/public/js/components/header/cattol/segment_filter/SegmentsFilter.js b/public/js/components/header/cattol/segment_filter/SegmentsFilter.js index b8dacd7939..e6d6883aca 100644 --- a/public/js/components/header/cattol/segment_filter/SegmentsFilter.js +++ b/public/js/components/header/cattol/segment_filter/SegmentsFilter.js @@ -10,6 +10,9 @@ import {SEGMENTS_STATUS} from '../../../../constants/Constants' import {Select} from '../../../common/Select' import Switch from '../../../common/Switch' import {DataSampleDropdown} from './DataSampleDropdown' +import {Button, BUTTON_MODE, BUTTON_SIZE} from '../../../common/Button/Button' +import ChevronLeft from '../../../../../img/icons/ChevronLeft' +import ChevronRight from '../../../../../img/icons/ChevronRight' class SegmentsFilter extends React.Component { constructor(props) { @@ -472,18 +475,20 @@ class SegmentsFilter extends React.Component {
{this.state.filteredCount} Filtered segments
- - + + +
) : null} {this.state.filtering && diff --git a/public/js/components/header/manage/FilterProjects.js b/public/js/components/header/manage/FilterProjects.js index c617907d44..0b610c8c10 100644 --- a/public/js/components/header/manage/FilterProjects.js +++ b/public/js/components/header/manage/FilterProjects.js @@ -1,93 +1,77 @@ -import React from 'react' -import {isUndefined} from 'lodash' +import React, { + useState, + useRef, + useCallback, + forwardRef, + useImperativeHandle, +} from 'react' import FilterProjectsStatus from './FilterProjectsStatus' import SearchInput from './SearchInput' import ManageActions from '../../../actions/ManageActions' import ManageConstants from '../../../constants/ManageConstants' -import MembersFilter from './MembersFilter' -class FilterProjects extends React.Component { - constructor(props) { - super(props) +const FilterProjects = forwardRef((props, ref) => { + const [currentStatus, setCurrentStatus] = useState('active') + const [currentUser, setCurrentUser] = useState( + ManageConstants.ALL_MEMBERS_FILTER, + ) + const currentText = useRef() - this.state = { - currentStatus: 'active', - currentUser: ManageConstants.ALL_MEMBERS_FILTER, - } - } + const handleSetCurrentUser = useCallback( + (value) => { + setCurrentUser(value) - setCurrentUser = (value) => { - this.setState({currentUser: value}) + ManageActions.filterProjects( + typeof value === 'object' ? value.user.uid : value, + currentText.current, + currentStatus, + ) + }, + [currentStatus], + ) - ManageActions.filterProjects( - typeof value === 'object' ? value.user.uid : value, - this.currentText, - this.state.currentStatus, - ) - } + const onChangeSearchInput = useCallback( + (value) => { + if ( + currentText.current !== value + ) + ManageActions.filterProjects( + typeof currentUser === 'object' ? currentUser.user.uid : currentUser, + value, + currentStatus, + ) - onChangeSearchInput(value) { - this.currentText = value - const {currentStatus, currentUser} = this.state + currentText.current = value + }, + [currentStatus, currentUser], + ) - ManageActions.filterProjects( - typeof currentUser === 'object' ? currentUser.user.uid : currentUser, - value, - currentStatus, - ) - } + const filterByStatus = useCallback( + (status) => { + setCurrentStatus(status) - filterByStatus(status) { - this.setState({currentStatus: status}) - const {currentUser} = this.state + ManageActions.filterProjects( + typeof currentUser === 'object' ? currentUser.user.uid : currentUser, + currentText.current, + status, + ) + }, + [currentUser], + ) - ManageActions.filterProjects( - typeof currentUser === 'object' ? currentUser.user.uid : currentUser, - this.currentText, - status, - ) - } + useImperativeHandle(ref, () => ({ + currentUser, + handleSetCurrentUser, + })) - shouldComponentUpdate(nextProps, nextState) { - return ( - isUndefined(this.props.selectedTeam) || - (!isUndefined(nextProps.selectedTeam) && - !nextProps.selectedTeam.equals(this.props.selectedTeam)) || - nextState.currentUser !== this.state.currentUser - ) - } + return ( +
+ + +
+ ) +}) - render() { - const canRenderMemebersFilter = - this.props.selectedTeam && - this.props.selectedTeam.get('type') === 'general' && - this.props.selectedTeam.get('members') && - this.props.selectedTeam.get('members').size > 1 - - return ( -
-
-
-
- - -
-
-
- {canRenderMemebersFilter && ( - - )} -
-
-
- ) - } -} +FilterProjects.displayName = 'FilterProjects' export default FilterProjects diff --git a/public/js/components/header/manage/FilterProjects.test.js b/public/js/components/header/manage/FilterProjects.test.js index 196eba1959..fd6cf09b7a 100644 --- a/public/js/components/header/manage/FilterProjects.test.js +++ b/public/js/components/header/manage/FilterProjects.test.js @@ -1225,7 +1225,7 @@ test('Rendering elements', () => { render() expect(screen.getByTestId('input-search-projects')).toBeInTheDocument() - expect(screen.getByTestId('status-filter')).toBeInTheDocument() + expect(screen.getByTestId('status-filter-trigger')).toBeInTheDocument() }) test('Searching with no result', async () => { @@ -1233,7 +1233,6 @@ test('Searching with no result', async () => { const {props} = getFakeProperties(fakeFilterData.teamWithId_1) render() - const searchTerm = 'my project' addOnceListenerStoreFilterProjects(() => getProjectsRequest({searchTerm})) diff --git a/public/js/components/header/manage/FilterProjectsStatus.js b/public/js/components/header/manage/FilterProjectsStatus.js index 364e8ffb40..fed1ce8834 100644 --- a/public/js/components/header/manage/FilterProjectsStatus.js +++ b/public/js/components/header/manage/FilterProjectsStatus.js @@ -27,25 +27,23 @@ const FilterProjectsStatus = ({filterFunction}) => { })) return ( -
- - - {STATES.find(({value}) => value === currentState)?.label} - - ), - }} - items={items} - /> -
+ + + {STATES.find(({value}) => value === currentState)?.label} + + ), + }} + items={items} + /> ) } diff --git a/public/js/components/header/manage/MembersFilter.js b/public/js/components/header/manage/MembersFilter.js index 892481c58a..ec3bf0ef86 100644 --- a/public/js/components/header/manage/MembersFilter.js +++ b/public/js/components/header/manage/MembersFilter.js @@ -1,4 +1,4 @@ -import React, {useCallback, useRef, useState} from 'react' +import React, {useState} from 'react' import PropTypes from 'prop-types' import ManageConstants from '../../../constants/ManageConstants' import {Button, BUTTON_SIZE, BUTTON_TYPE} from '../../common/Button/Button' @@ -8,12 +8,11 @@ import {Input, INPUT_SIZE} from '../../common/Input/Input' import IconSearch from '../../icons/IconSearch' import IconDown from '../../icons/IconDown' import LabelWithTooltip from '../../common/LabelWithTooltip' +import * as Popover from '@radix-ui/react-popover' const MembersFilter = ({selectedTeam, currentUser, setCurrentUser}) => { - const [isDropdownVisible, setIsDropdownVisible] = useState(false) const [searchFilter, setSearchFilter] = useState() - - const wrapperRef = useRef() + const [open, setOpen] = useState(false) const getImgUser = (userData) => { const {user_metadata: metadata, user} = userData @@ -28,37 +27,9 @@ const MembersFilter = ({selectedTeam, currentUser, setCurrentUser}) => { ) } - const closeDropdown = useCallback((e) => { - if (e) e.stopPropagation() - if (wrapperRef.current && !wrapperRef.current.contains(e?.target)) { - window.eventHandler.removeEventListener( - 'click.membersfilterdropdown', - closeDropdown, - ) - - setIsDropdownVisible(false) - } - }, []) - - const toggleDropdown = () => { - if (isDropdownVisible) { - window.eventHandler.removeEventListener( - 'click.membersfilterdropdown', - closeDropdown, - ) - } else { - window.eventHandler.addEventListener( - 'click.membersfilterdropdown', - closeDropdown, - ) - } - - setIsDropdownVisible((prevState) => !prevState) - } - const onChangeUserCallback = (data) => { setCurrentUser(data) - closeDropdown() + setOpen(false) } const teamMembers = selectedTeam.get('members').toJS() @@ -73,86 +44,98 @@ const MembersFilter = ({selectedTeam, currentUser, setCurrentUser}) => { : teamMembers return ( -
- -
-
    -
  • - onChangeUserCallback(ManageConstants.NOT_ASSIGNED_FILTER) - } - > - NA - Not assigned -
  • -
  • - onChangeUserCallback(ManageConstants.ALL_MEMBERS_FILTER) - } - > - ALL - All Members -
  • -
  • - setSearchFilter(value)} - icon={} - /> -
  • - {filteredMembers.length > 0 ? ( - filteredMembers.map((userData) => ( + + + + + + +
    +
    • onChangeUserCallback(userData)} + className={`members-filter-item-filter ${currentUser === ManageConstants.NOT_ASSIGNED_FILTER ? 'active' : ''}`} + onClick={() => + onChangeUserCallback(ManageConstants.NOT_ASSIGNED_FILTER) + } > -
      - {getImgUser(userData)} - {`${userData.user.first_name} ${userData.user.last_name}`} -
      - {userData.projects} + NA + Not assigned
    • - )) - ) : ( - No results found. - )} -
    -
    -
+
  • + onChangeUserCallback(ManageConstants.ALL_MEMBERS_FILTER) + } + > + ALL + All Members +
  • +
  • + + setSearchFilter(value) + } + icon={} + /> +
  • + {filteredMembers.length > 0 ? ( + filteredMembers.map((userData) => ( +
  • onChangeUserCallback(userData)} + > +
    + {getImgUser(userData)} + {`${userData.user.first_name} ${userData.user.last_name}`} +
    + {userData.projects} +
  • + )) + ) : ( + + No results found. + + )} + +
    + + + ) } diff --git a/public/js/components/header/manage/SearchInput.js b/public/js/components/header/manage/SearchInput.js index 9c00f06951..b1f3283e5a 100644 --- a/public/js/components/header/manage/SearchInput.js +++ b/public/js/components/header/manage/SearchInput.js @@ -1,70 +1,43 @@ -import React from 'react' -import {debounce} from 'lodash' -import $ from 'jquery' +import React, {useEffect} from 'react' +import {Input} from '../../common/Input/Input' +import IconSearch from '../../icons/IconSearch' -class SearchInput extends React.Component { - constructor(props) { - super(props) - this.onKeyPressEvent = this.onKeyPressEvent.bind(this) - let self = this - this.filterByNameDebounce = debounce(function (e) { - self.filterByName(e) - }, 500) - } - - filterByName(e) { - if ($(this.textInput).val().length) { - $(this.closeIcon).show() - } else { - $(this.closeIcon).hide() - } +const SearchInput = ({onChange}) => { + const [searchFilter, setSearchFilter] = React.useState('') - this.props.onChange($(this.textInput).val()) + useEffect(() => { + const tmOut = setTimeout(() => { + onChange(searchFilter) + }, 500) - return false - } + return () => clearTimeout(tmOut) + }, [searchFilter, onChange]) - closeSearch() { - $(this.textInput).val('') - $(this.closeIcon).hide() - this.props.onChange($(this.textInput).val()) + const closeSearch = () => { + setSearchFilter('') + onChange('') } - onKeyPressEvent(e) { + const onKeyPressEvent = (e) => { if (e.which == 27) { - this.closeSearch() - } else { - if (e.which == 13 || e.keyCode == 13) { - e.preventDefault() - return false - } + closeSearch() + } else if (e.which == 13 || e.keyCode == 13) { + e.preventDefault() + return false } } - render() { - return ( - (this.textInput = input)} - onChange={this.filterByNameDebounce.bind(this)} - onKeyPress={this.onKeyPressEvent.bind(this)} - data-testid="input-search-projects" - /> - - /*
    -
    - this.textInput = input} - onChange={this.filterByNameDebounce.bind(this)} - onKeyPress={this.onKeyPressEvent.bind(this)}/> - {/!**!/} -
    -
    */ - ) - } + return ( + setSearchFilter(e.target.value)} + onKeyPress={onKeyPressEvent} + icon={} + data-testid="input-search-projects" + /> + ) } export default SearchInput diff --git a/public/js/components/icons/IconQR.js b/public/js/components/icons/IconQR.js deleted file mode 100644 index 1e7e64ece5..0000000000 --- a/public/js/components/icons/IconQR.js +++ /dev/null @@ -1,38 +0,0 @@ -import React from 'react' - -export const IconQR = ({ - width = '42', - height = width, - color1 = '#FAFAFA', - color2 = '#FFFFFF', -}) => { - return ( - - - - - - - ) -} diff --git a/public/js/components/icons/Star.js b/public/js/components/icons/Star.js new file mode 100644 index 0000000000..10ce6824b3 --- /dev/null +++ b/public/js/components/icons/Star.js @@ -0,0 +1,21 @@ +import React from 'react' +import PropTypes from 'prop-types' + +const Star = ({size = 24}) => { + return ( + + + + ) +} + +Star.propTypes = { + size: PropTypes.number, +} + +export default Star diff --git a/public/js/components/languageSelector/LanguageSelector.js b/public/js/components/languageSelector/LanguageSelector.js index 53bdd5d733..f8697dd14b 100644 --- a/public/js/components/languageSelector/LanguageSelector.js +++ b/public/js/components/languageSelector/LanguageSelector.js @@ -3,6 +3,14 @@ import React from 'react' import LanguageSelectorList from './LanguageSelectorList' import LanguageSelectorSearch from './LanguageSelectorSearch' import LabelWithTooltip from '../common/LabelWithTooltip' +import { + Button, + BUTTON_MODE, + BUTTON_SIZE, + BUTTON_TYPE, +} from '../common/Button/Button' +import FlipBackwardIcon from '../../../img/icons/FlipBackwardIcon' +import Close from '../../../img/icons/Close' const RECENTLY_USED_LOCAL_STORAGE_KEY = `target_languages_recently_used-${config.userMail}` const MAX_RECENTLY_USED_STORED = 3 @@ -127,7 +135,14 @@ class LanguageSelector extends React.Component {
    Target languages - +
    @@ -182,13 +197,14 @@ class LanguageSelector extends React.Component { {(filteredLanguages.length > 0 || (querySearch && !filteredLanguages.length)) && (
    - +
    )}
    @@ -253,9 +269,9 @@ class LanguageSelector extends React.Component {
    - +
    diff --git a/public/js/components/modals/AlertModal.js b/public/js/components/modals/AlertModal.js index 9efbb65d76..51ac720f07 100644 --- a/public/js/components/modals/AlertModal.js +++ b/public/js/components/modals/AlertModal.js @@ -1,5 +1,6 @@ import PropTypes from 'prop-types' import React from 'react' +import {Button, BUTTON_TYPE} from '../common/Button/Button' class AlertModal extends React.Component { allowHTML(string) { @@ -25,12 +26,12 @@ class AlertModal extends React.Component { )}
    -
    this.closeModal()} > {this.props.buttonText ? this.props.buttonText : 'Ok'} -
    +
    diff --git a/public/js/components/modals/ConfirmMessageModal.js b/public/js/components/modals/ConfirmMessageModal.js index 7782d48e21..8b3f835392 100644 --- a/public/js/components/modals/ConfirmMessageModal.js +++ b/public/js/components/modals/ConfirmMessageModal.js @@ -1,5 +1,6 @@ import PropTypes from 'prop-types' import React from 'react' +import {Button, BUTTON_MODE, BUTTON_TYPE} from '../common/Button/Button' class ConfirmMessageModal extends React.Component { allowHTML(string) { @@ -18,43 +19,44 @@ class ConfirmMessageModal extends React.Component { this.props.text )}
    -
    +
    {this.props.cancelCallback || this.props.cancelText ? ( -
    { if (this.props.closeOnSuccess) this.props.onClose() this.props.cancelCallback?.() }} > {this.props.cancelText ? this.props.cancelText : 'Cancel'} -
    + ) : ( '' )} {this.props.warningCallback ? ( -
    { if (this.props.closeOnSuccess) this.props.onClose() this.props.warningCallback?.() }} > {this.props.warningText} -
    + ) : ( '' )} {this.props.successCallback || this.props.successText ? ( -
    { if (this.props.closeOnSuccess) this.props.onClose() this.props.successCallback?.() }} > {this.props.successText ? this.props.successText : 'Confirm'} -
    + ) : ( '' )} diff --git a/public/js/components/modals/CreateTeam.js b/public/js/components/modals/CreateTeam.js index e4c3c9d5ae..88be05a7e5 100644 --- a/public/js/components/modals/CreateTeam.js +++ b/public/js/components/modals/CreateTeam.js @@ -8,6 +8,7 @@ import {EMAIL_PATTERN} from '../../constants/Constants' import ManageActions from '../../actions/ManageActions' import ModalsActions from '../../actions/ModalsActions' import {ApplicationWrapperContext} from '../common/ApplicationWrapper/ApplicationWrapperContext' +import {Button, BUTTON_TYPE} from '../common/Button/Button' export const CreateTeam = () => { const {userInfo} = useContext(ApplicationWrapperContext) @@ -47,7 +48,7 @@ export const CreateTeam = () => { Create a team and invite your colleagues to share and manage projects.

    -

    Assign a name to your team

    +
    Assign a name to your team
    {
    -

    Add members

    +
    Add members
    {
    - +
    ) } diff --git a/public/js/components/modals/JobMetadataModal.js b/public/js/components/modals/JobMetadataModal.js index c900a96815..49d453499e 100644 --- a/public/js/components/modals/JobMetadataModal.js +++ b/public/js/components/modals/JobMetadataModal.js @@ -52,17 +52,11 @@ class JobMetadataModal extends React.Component { const title = (
    - - {file.file_name} - + {CommonUtils.getFileIcon( + file.file_name.split('.')[file.file_name.split('.').length - 1], + )} + + {file.file_name}
    ) diff --git a/public/js/components/modals/ModalContainer.js b/public/js/components/modals/ModalContainer.js index 69541741b7..eea0f41a4f 100644 --- a/public/js/components/modals/ModalContainer.js +++ b/public/js/components/modals/ModalContainer.js @@ -1,4 +1,11 @@ import React, {useEffect, useRef} from 'react' +import Close from '../../../img/icons/Close' +import { + Button, + BUTTON_MODE, + BUTTON_SIZE, + BUTTON_TYPE, +} from '../common/Button/Button' export const ModalContainer = ({ title, @@ -72,13 +79,15 @@ export const ModalContainer = ({

    {title}

    {!isCloseButtonDisabled && ( -
    - -
    + )}
    )} diff --git a/public/js/components/modals/ModalOverlay.js b/public/js/components/modals/ModalOverlay.js index b3971eb54d..0045ad5d72 100644 --- a/public/js/components/modals/ModalOverlay.js +++ b/public/js/components/modals/ModalOverlay.js @@ -1,14 +1,18 @@ import React from 'react' import $ from 'jquery' +import { + Button, + BUTTON_MODE, + BUTTON_SIZE, + BUTTON_TYPE, +} from '../common/Button/Button' +import Close from '../../../img/icons/Close' export const ModalOverlay = ({title, styleContainer, children, onClose}) => { const handleClose = (e) => { e.stopPropagation() - if ( - $(e.target).closest('.matecat-modal-content').length == 0 || - $(e.target).hasClass('close-matecat-modal') - ) { + if (onClose) { onClose() } } @@ -18,11 +22,7 @@ export const ModalOverlay = ({title, styleContainer, children, onClose}) => { }, []) return ( -
    +
    @@ -30,14 +30,15 @@ export const ModalOverlay = ({title, styleContainer, children, onClose}) => {

    {title}

    - -
    - -
    +
    {children}
    diff --git a/public/js/components/modals/ModifyTeam.js b/public/js/components/modals/ModifyTeam.js index 43932c7a0d..fb45b66af9 100644 --- a/public/js/components/modals/ModifyTeam.js +++ b/public/js/components/modals/ModifyTeam.js @@ -127,28 +127,29 @@ export const ModifyTeam = ({team}) => { {removeUserId === user.get('uid') ? (
    - + - +
    ) : ( -
    confirmRemoveMember(user.get('uid'))} > Remove -
    + )} ) @@ -185,12 +186,13 @@ export const ModifyTeam = ({team}) => { ) : ( <> Pending user -
    resendInvite(email)} > Resend Invite -
    + )}
    @@ -248,7 +250,7 @@ export const ModifyTeam = ({team}) => { return (
    -

    Change Team Name

    +
    Change Team Name
    {isModifyingName ? (
    @@ -260,11 +262,7 @@ export const ModifyTeam = ({team}) => { autoFocus onKeyDown={handleEnterKeyConfirmName} /> -
    {teamState.get('type') !== 'personal' && (
    -

    Manage Members

    +
    Manage Members
    { onChange={onChangeAddMembers} placeholder="Add new members by entering their email addresses" /> - +
    + +
    )} @@ -336,12 +337,13 @@ export const ModifyTeam = ({team}) => { {userlist}
    - +
    ) } diff --git a/public/js/components/modals/RevisionFeedbackModal.js b/public/js/components/modals/RevisionFeedbackModal.js index 4510518edf..7b0c6cd3d3 100644 --- a/public/js/components/modals/RevisionFeedbackModal.js +++ b/public/js/components/modals/RevisionFeedbackModal.js @@ -2,6 +2,7 @@ import React from 'react' import CatToolActions from '../../actions/CatToolActions' import ModalsActions from '../../actions/ModalsActions' +import {Button, BUTTON_TYPE} from '../common/Button/Button' class RevisionFeedbackModal extends React.Component { constructor(props) { @@ -83,34 +84,31 @@ class RevisionFeedbackModal extends React.Component {
    -
    -
    -
    ModalsActions.onCloseModal()} - > - {this.props.feedback ? 'Close' : "I'll do it later"} -
    +
    + - {this.state.sending ? ( -
    - - {sendLabel} -
    - ) : !this.state.buttonEnabled ? ( -
    {sendLabel}
    - ) : ( -
    this.sendFeedback()} - > - {sendLabel} -
    - )} -
    + {this.state.sending ? ( + + ) : !this.state.buttonEnabled ? ( + + ) : ( + + )}
    diff --git a/public/js/components/modals/ShareTmModal.js b/public/js/components/modals/ShareTmModal.js index e86bfeae16..c6a2979048 100644 --- a/public/js/components/modals/ShareTmModal.js +++ b/public/js/components/modals/ShareTmModal.js @@ -3,6 +3,7 @@ import React from 'react' import CommonUtils from '../../utils/commonUtils' import {shareTmKey} from '../../api/shareTmKey' import CatToolActions from '../../actions/CatToolActions' +import {Button, BUTTON_TYPE} from '../common/Button/Button' class ShareTmModal extends React.Component { constructor(props) { @@ -124,12 +125,12 @@ class ShareTmModal extends React.Component { ref={(input) => (this.emails = input)} onKeyUp={(e) => this.onKeyUp(e)} /> - +
    {errorEmailsResult && ( diff --git a/public/js/components/modals/SplitJob.js b/public/js/components/modals/SplitJob.js index fd497b557d..32f0a25779 100644 --- a/public/js/components/modals/SplitJob.js +++ b/public/js/components/modals/SplitJob.js @@ -10,6 +10,7 @@ import { BUTTON_TYPE, } from '../common/Button/Button' import Tooltip from '../common/Tooltip' +import {SpinnerLoader} from '../common/SpinnerLoader' const SplitJobModal = ({job, project, callback}) => { const [numSplit, setNumSplit] = useState(2) @@ -211,9 +212,7 @@ const SplitJobModal = ({job, project, callback}) => { } else if (!wordsArray) { return (
    -
    -
    Loading
    -
    +
    ) } @@ -345,19 +344,11 @@ const SplitJobModal = ({job, project, callback}) => {
    )} {showLoader &&
    } - {!showSplitDiffError && splitChecked && ( - )} diff --git a/public/js/components/modals/SupportedFilesModal.js b/public/js/components/modals/SupportedFilesModal.js index 5524bd86d0..5dc8c94a7b 100644 --- a/public/js/components/modals/SupportedFilesModal.js +++ b/public/js/components/modals/SupportedFilesModal.js @@ -1,4 +1,5 @@ import React from 'react' +import CommonUtils from '../../utils/commonUtils' const SupportedFilesModal = ({supportedFiles}) => { const keys = Object.keys(supportedFiles) @@ -8,11 +9,12 @@ const SupportedFilesModal = ({supportedFiles}) => {
    {keys.map((name) => (
    -

    {name}

    +

    {name}

    {supportedFiles[name].map((item, index) => (
    - {item[0].ext} + {CommonUtils.getFileIcon(item[0].ext)} + {item[0].ext}
    ))}
    diff --git a/public/js/components/modals/UnlockAllSegmentsModal.js b/public/js/components/modals/UnlockAllSegmentsModal.js index be3f47393a..93113d47f2 100644 --- a/public/js/components/modals/UnlockAllSegmentsModal.js +++ b/public/js/components/modals/UnlockAllSegmentsModal.js @@ -3,6 +3,7 @@ import SegmentStore from '../../stores/SegmentStore' import {getFilteredSegments} from '../../api/getFilteredSegments' import SegmentActions from '../../actions/SegmentActions' import ModalsActions from '../../actions/ModalsActions' +import {Button, BUTTON_TYPE} from '../common/Button/Button' export const HIDE_UNLOCK_ALL_SEGMENTS_MODAL_STORAGE = 'unlock-segments-modal' + config.id_job @@ -32,9 +33,8 @@ export const UnlockAllSegmentsModal = () => {
    Would you like to unlock all 101% segments?
    -
    -
    +
    -
    + +
    +
    { text={notification.text} autoDismiss={notification.autoDismiss} onRemove={closeNotification} - allowHtml={notification.allowHtml} timer={notification.timer} closeCallback={notification.closeCallback} openCallback={notification.openCallback} @@ -148,7 +146,7 @@ const NotificationBox = () => { return (
    {items} diff --git a/public/js/components/notificationsComponent/NotificationItem.js b/public/js/components/notificationsComponent/NotificationItem.js index 91cba7dffd..53afe1f7f6 100644 --- a/public/js/components/notificationsComponent/NotificationItem.js +++ b/public/js/components/notificationsComponent/NotificationItem.js @@ -1,5 +1,14 @@ import PropTypes from 'prop-types' import React, {useState, useRef, useEffect} from 'react' +import IconClose from '../icons/IconClose' +import { + Button, + BUTTON_MODE, + BUTTON_SIZE, + BUTTON_TYPE, +} from '../common/Button/Button' +import InfoIcon from '../../../img/icons/InfoIcon' +import CheckCircleBroken from '../../../img/icons/CheckCircleBroken' const NotificationItem = ({ uid, @@ -10,7 +19,6 @@ const NotificationItem = ({ autoDismiss = true, closeCallback, openCallback, - allowHtml = false, timer = 7000, dismissable = true, onRemove, @@ -18,11 +26,10 @@ const NotificationItem = ({ }) => { const [visible, setVisible] = useState(false) const [removed, setRemoved] = useState(false) - + let _isMounted = useRef() const styleNameContainer = 'notification-type-' + type - const styleNameTitle = 'notification-title-' + type let _notificationTimer = useRef() const hideNotification = () => { @@ -66,10 +73,6 @@ const NotificationItem = ({ } }, [remove]) - const allowHTML = (string) => { - return {__html: string} - } - const getCssPropertyByPosition = () => { let css = {} @@ -121,32 +124,34 @@ const NotificationItem = ({ return notificationStyle } + const icon = + type === 'success' ? ( + + ) : ( + + ) + return ( -
    - {dismissable ? ( - +
    +
    {icon}
    +
    +
    {title}
    +

    {text}

    +
    +
    + {dismissable && ( + )}
    ) @@ -154,13 +159,12 @@ const NotificationItem = ({ NotificationItem.propTypes = { position: PropTypes.string, - title: PropTypes.string.isRequired, + title: PropTypes.oneOfType([PropTypes.string, PropTypes.node]).isRequired, text: PropTypes.oneOfType([PropTypes.string, PropTypes.node]).isRequired, type: PropTypes.string, autoDismiss: PropTypes.bool, closeCallback: PropTypes.func, openCallback: PropTypes.func, - allowHtml: PropTypes.bool, timer: PropTypes.number, dismissable: PropTypes.bool, } diff --git a/public/js/components/onBoarding/OnBoarding.js b/public/js/components/onBoarding/OnBoarding.js index 3715418896..897acc6fa7 100644 --- a/public/js/components/onBoarding/OnBoarding.js +++ b/public/js/components/onBoarding/OnBoarding.js @@ -87,7 +87,7 @@ const OnBoarding = ({ {isCloseButtonEnabled && (
    ', } } - showShareTranslatorError() { + + const showShareTranslatorError = () => { ModalsActions.onCloseModal() - const notification = { + CatToolActions.addNotification({ title: 'Problems sending the job', text: 'Please try later or contact support@matecat.com', type: 'error', position: 'bl', allowHtml: true, timer: 10000, - } - CatToolActions.addNotification(notification) - } - - GmtSelectChanged(value) { - this.checkSendToTranslatorButton() - this.setState({ - timezone: value, }) } - checkSendToTranslatorButton() { - if ( - this.email.value.length > 0 && - CommonUtils.checkEmail(this.email.value) - ) { - $(this.sendButton).removeClass('disabled') - return true + const checkShareToTranslatorResponse = ( + response, + mail, + date, + jobData, + projectData, + ) => { + let message = '' + if (jobData.translator) { + const newDate = new Date(date) + const oldDate = new Date(jobData.translator.delivery_date) + if (oldDate.getTime() !== newDate.getTime()) { + message = shareToTranslatorDateChangeNotification( + mail, + oldDate, + newDate, + ) + } else if (jobData.translator.email !== mail) { + message = shareToTranslatorMailChangeNotification(mail, jobData) + } else { + message = shareToTranslatorNotification(mail, jobData) + } } else { - $(this.sendButton).addClass('disabled') + message = shareToTranslatorNotification(mail, jobData) } + CatToolActions.addNotification({ + title: message.title, + text: message.text, + type: 'success', + position: 'bl', + allowHtml: true, + timer: 10000, + }) + ManageActions.changeJobPasswordFromOutsource( + projectData, + jobData, + jobData.password, + response.job.password, + ) + ManageActions.assignTranslator( + projectData.id, + jobData.id, + jobData.password, + response.job.translator, + ) } - render() { - let translatorEmail = '' - if (this.props.job.get('translator')) { - translatorEmail = this.props.job.get('translator').get('email') - } - const timeOptions = [ - {name: '1:00 AM', id: '1'}, - {name: '2:00 AM', id: '2'}, - {name: '3:00 AM', id: '3'}, - {name: '4:00 AM', id: '4'}, - {name: '5:00 AM', id: '5'}, - {name: '6:00 AM', id: '6'}, - {name: '7:00 AM', id: '7'}, - {name: '8:00 AM', id: '8'}, - {name: '9:00 AM', id: '9'}, - {name: '10:00 AM', id: '10'}, - {name: '11:00 AM', id: '11'}, - {name: '12:00 AM', id: '12'}, - {name: '1:00 PM', id: '13'}, - {name: '2:00 PM', id: '14'}, - {name: '3:00 PM', id: '15'}, - {name: '4:00 PM', id: '16'}, - {name: '5:00 PM', id: '17'}, - {name: '6:00 PM', id: '18'}, - {name: '7:00 PM', id: '19'}, - {name: '8:00 PM', id: '20'}, - {name: '9:00 PM', id: '21'}, - {name: '10:00 PM', id: '22'}, - {name: '11:00 PM', id: '23'}, - {name: '12:00 PM', id: '24'}, - ] - return ( -
    -
    Assign Job to translator
    -
    -
    -
    -
    -
    - - (this.email = email)} - onKeyUp={this.checkSendToTranslatorButton.bind(this)} - /> -
    -
    - -
    -
    - { - this.setState({ - deliveryDate: date, - }) - this.checkSendToTranslatorButton() - }} - /> -
    + const shareJob = () => { + const date = new Date(deliveryDate) + date.setHours(parseInt(time)) + date.setMinutes(0) + + const email = emailRef.current.value + const jobData = job.toJS() + const projectData = project.toJS() + + addJobTranslator(email, date, timezone, jobData) + .then((data) => { + ModalsActions.onCloseModal() + if (data.job) { + checkShareToTranslatorResponse( + data, + email, + date, + jobData, + projectData, + ) + } else { + showShareTranslatorError() + } + }) + .catch(() => { + showShareTranslatorError() + }) + closeOutsource() + } + + const translatorEmail = job.get('translator') + ? job.get('translator').get('email') + : '' + + return ( +
    +
    Assign Job to translator
    +
    +
    +
    +
    +
    + + +
    +
    + +
    +
    + { + setDeliveryDate(date) + checkSendToTranslatorButton() + }} + />
    -
    - { + setTime(id) + checkSendToTranslatorButton() + }} + activeOption={timeOptions.find(({id}) => id === time)} + options={timeOptions} + /> +
    +
    + { + checkSendToTranslatorButton() + setTimezone(value) + }} + showLabel={true} + /> +
    +
    +
    - ) - } +
    + ) } export default AssignToTranslator diff --git a/public/js/components/outsource/GMTSelect.js b/public/js/components/outsource/GMTSelect.js index 9517ddadca..752d883be0 100644 --- a/public/js/components/outsource/GMTSelect.js +++ b/public/js/components/outsource/GMTSelect.js @@ -2,131 +2,52 @@ import React, {useState} from 'react' import Cookies from 'js-cookie' import {Select} from '../common/Select' +const GMT_OPTIONS = [ + {name: '(GMT -11:00 ) Midway Islands Time', id: '-11'}, + {name: '(GMT -10:00 ) Hawaii Standard Time', id: '-10'}, + {name: '(GMT -9:00 ) Alaska Standard Time', id: '-9'}, + {name: '(GMT -8:00 ) Pacific Standard Time', id: '-8'}, + {name: '(GMT -7:00 ) Mountain Standard Time', id: '-7'}, + {name: '(GMT -6:00 ) Central Standard Time', id: '-6'}, + {name: '(GMT -5:00 ) Eastern Standard Time', id: '-5'}, + {name: '(GMT -4:00 ) Atlantic Standard Time', id: '-4'}, + {name: '(GMT -3:00 ) Brazil Eastern Time, Argentina Standard Time', id: '-3'}, + {name: '(GMT -2:00 ) South Sandwich Islands', id: '-2'}, + {name: '(GMT -1:00 ) Central African Time', id: '-1'}, + {name: '(GMT) Greenwich Mean Time', id: '0'}, + {name: '(GMT +1:00 ) European Central Time', id: '1'}, + {name: '(GMT +2:00 ) Eastern European Time', id: '2'}, + {name: '(GMT +3:00 ) Eastern African Time', id: '3'}, + {name: '(GMT +3.30 ) Middle East Time', id: '3.5'}, + {name: '(GMT +4.00 ) Near East Time', id: '4'}, + {name: '(GMT +5.00 ) Pakistan Lahore Time', id: '5'}, + {name: '(GMT +5.30 ) India Standard Time', id: '5.5'}, + {name: '(GMT +6.00 ) Bangladesh Standard Time', id: '6'}, + {name: '(GMT +7.00 ) Vietnam Standard Time', id: '7'}, + {name: '(GMT +8.00 ) China Taiwan Time', id: '8'}, + {name: '(GMT +9.00 ) Japan Standard Time', id: '9'}, + {name: '(GMT +9.30 ) Australia Central Time', id: '9.5'}, + {name: '(GMT +10.00 ) Australia Eastern Time', id: '10'}, + {name: '(GMT +11.00 ) Solomon Standard Time', id: '11'}, + {name: '(GMT +12.00 ) New Zealand Standard Time', id: '12'}, +] + export const GMTSelect = ({showLabel, changeValue}) => { - const timezoneToShow = Cookies.get('matecat_timezone') - const [timezone, setTimezone] = useState(timezoneToShow) - const items = [ - { - name: '(GMT -11:00 ) Midway Islands Time', - id: '-11', - }, - { - name: '(GMT -10:00 ) Hawaii Standard Time', - id: '-10', - }, - { - name: '(GMT -9:00 ) Alaska Standard Time', - id: '-9', - }, - { - name: '(GMT -8:00 ) Pacific Standard Time', - id: '-8', - }, - { - name: '(GMT -7:00 ) Mountain Standard Time', - id: '-7', - }, - { - name: '(GMT -6:00 ) Central Standard Time', - id: '-6', - }, - { - name: '(GMT -5:00 ) Eastern Standard Time', - id: '-5', - }, - { - name: '(GMT -4:00 ) Atlantic Standard Time', - id: '-4', - }, - { - name: '(GMT -3:00 ) Brazil Eastern Time, Argentina Standard Time', - id: '-3', - }, - { - name: '(GMT -2:00 ) South Sandwich Islands', - id: '-2', - }, - { - name: '(GMT -1:00 ) Central African Time', - id: '-1', - }, - { - name: '(GMT) Greenwich Mean Time', - id: '0', - }, - { - name: '(GMT +1:00 ) European Central Time ', - id: '1', - }, - { - name: '(GMT +2:00 ) Eastern European Time', - id: '2', - }, - { - name: '(GMT +3:00 ) Eastern African Time ', - id: '3', - }, - { - name: '(GMT +3.30 ) Middle East Time', - id: '3.5', - }, - { - name: '(GMT +4.00 ) Near East Time', - id: '4', - }, - { - name: '(GMT +5.00 ) Pakistan Lahore Time', - id: '5', - }, - { - name: '(GMT +5.30 ) India Standard Time', - id: '5.5', - }, - { - name: '(GMT +6.00 ) Bangladesh Standard Time ', - id: '6', - }, - { - name: '(GMT +7.00 ) Vietnam Standard Time ', - id: '7', - }, - { - name: '(GMT +8.00 ) China Taiwan Time ', - id: '8', - }, - { - name: '(GMT +9.00 ) Japan Standard Time ', - id: '9', - }, - { - name: '(GMT +9.30 ) Australia Central Time ', - id: '9.5', - }, - { - name: '(GMT +10.00 ) Australia Eastern Time ', - id: '10', - }, - { - name: '(GMT +11.00 ) Solomon Standard Time ', - id: '11', - }, - { - name: '(GMT +12.00 ) New Zealand Standard Time ', - id: '12', - }, - ] + const [timezone, setTimezone] = useState( + () => Cookies.get('matecat_timezone'), + ) return ( (this.revisionCheckbox = checkbox)} - onChange={this.clickRevision.bind(this)} - /> - -
    -
    - {this.state.outsourceConfirmed ? ( - '' - ) : ( -
    - {priceCurrencySymbol}{' '} - {this.getCurrencyPrice( - this.state.chunkQuote.get('r_price'), - ).replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1,')} -
    - )} -
    - {!this.state.errorQuote ? ( - !this.state.needItFaster ? ( -
    -
    - - -
    - {delivery.day + ' ' + delivery.month} -
    -
    at
    -
    {delivery.time}
    - -
    - - {/*
    GMT +2
    */} -
    - - {!this.state.outsourceConfirmed ? ( -
    - {this.state.errorPastDate ? ( -
    - * Chosen delivery date is in the past -
    - ) : null} - {this.state.quoteNotAvailable ? ( -
    - * Deadline too close, pick another one. -
    - ) : null} - - {showDateMessage ? ( -
    - We will deliver before the selected date -
    - -
    -
    - ) : ( - '' - )} - (this.dateFaster = faster)} - onClick={this.needItFaster.bind(this)} - > - Need it faster? - -
    - ) : ( - '' - )} -
    - {this.state.outsourceConfirmed && - !this.state.jobOutsourced ? ( -
    - -
    - Insert your email and we’ll start working on your - project instantly. -
    -
    - -
    -
    - ) : ( - '' - )} - {this.state.outsourceConfirmed && this.state.jobOutsourced ? ( -
    -
    Order sent correctly
    -

    - Thank you for choosing our Outsource service -
    - You will soon be contacted by a Account Manager to send - you an invoice -

    -
    - ) : ( - '' - )} -
    - ) : ( -
    - - - -
    -
    -
    -
    - -
    (this.calendar = calendar)} - > -
    - { - this.setState({ - deliveryDate: date, - }) - }} - /> -
    -
    -
    -
    - + + + + + + + ) +} - {/*
    * This is a generic error
    */} - {this.state.outsourceConfirmed && !this.state.jobOutsourced ? ( -
    - -
    - Great, an Account Manager will contact you to send you the - invoice as a customer to this email -
    -
    - -
    -
    - ) : ( - '' - )} -
    - {!this.state.errorQuote ? ( -
    -
    -
    - {priceCurrencySymbol}{' '} - {price.replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1,')} -
    - - - about {priceCurrencySymbol} {pricePWord} / word - - - ), - }} - items={Object.keys(this.currencies).map((key) => { - return { - label: this.currencies[key].name, - onClick: () => { - this.onCurrencyChange(key) - }, - } - })} - /> -
    -
    - {!this.state.outsourceConfirmed ? ( - - ) : // - !this.state.jobOutsourced ? ( - - ) : ( - - )} -
    -
    - ) : null} - {this.state.jobOutsourced ? ( -
    -
    Order sent correctly
    -

    Thank you for choosing our Outsource service.

    -
    - ) : ( - '' - )} -
    - ) : ( - this.getLoaderHtml() - )} +// --- Extended View --- +const ExtendedView = ({ + outsource, + revision, + chunkQuote, + outsourceConfirmed, + errorQuote, + job, + translatedWords, + priceCurrencySymbol, + getCurrencyPrice, + onToggleRevision, + translatorsNumber, + deliveryProps, + orderBoxProps, +}) => ( + <> + + + {outsource ? ( +
    + + + +
    + + {!errorQuote && } +
    - ) - } - - allowHTML(string) { - return {__html: string} - } - - componentDidMount() {} - - componentWillUnmount() { - // $(this.dateFaster).datetimepicker('destroy'); - } - - componentDidUpdate() { - if (this.state.outsource) { - if (this.state.extendedView) { - this.revisionCheckbox.checked = - this.state.chunkQuote.get('typeOfService') === 'premium' - ? true - : false - } - } - } - - shouldComponentUpdate(nextProps, nextState) { - return ( - (nextState.chunkQuote && - !nextState.chunkQuote.equals(this.state.chunkQuote)) || - nextState.outsource !== this.state.outsource || - nextState.extendedView !== this.state.extendedView || - nextState.revision !== this.state.revision || - nextState.timezone !== this.state.timezone || - nextState.outsourceConfirmed !== this.state.outsourceConfirmed || - nextState.jobOutsourced !== this.state.jobOutsourced || - nextState.errorPastDate !== this.state.errorPastDate || - nextState.quoteNotAvailable !== this.state.quoteNotAvailable || - nextState.needItFaster !== this.state.needItFaster || - nextState.deliveryDate !== this.state.deliveryDate || - nextState.selectedTime !== this.state.selectedTime - ) - } - - render() { - let containerClass = !this.state.extendedView ? 'compact-background' : '' - if (this.state.errorOutsource) { - return ( -
    -
    -
    -
    - Quote not available, please contact us at info@translated.net or - call +39 06 90 254 001 -
    + ) : ( +
    + +
    + )} + + +) + +// --- Compact View --- +const CompactView = ({ + outsource, + errorQuote, + onViewMore, + deliveryProps, + translatorsNumber, + orderBoxProps, +}) => ( + <> + {outsource ? ( +
    +
    +
    +
    Let us do it for you
    +
    + Outsource: PM+ + Translation+ + Revision
    + + View More
    + + {!errorQuote && }
    - ) - } else { - return ( -
    - {this.state.extendedView - ? this.getExtendedView() - : this.getCompactView()} -
    (this.outsourceForm = form)} - > - - - - - -
    -
    - ) - } - } -} +
    + ) : ( +
    + +
    + )} + +) export default OutsourceVendor diff --git a/public/js/components/outsource/OutsourceVendor.new.js b/public/js/components/outsource/OutsourceVendor.new.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/public/js/components/outsource/components/DeliverySection.js b/public/js/components/outsource/components/DeliverySection.js new file mode 100644 index 0000000000..8de104deee --- /dev/null +++ b/public/js/components/outsource/components/DeliverySection.js @@ -0,0 +1,136 @@ +import React from 'react' +import DatePicker from 'react-datepicker' + +import {GMTSelect} from '../GMTSelect' +import {Select} from '../../common/Select' +import {Button, BUTTON_MODE, BUTTON_TYPE} from '../../common/Button/Button' +import HelpCircle from '../../../../img/icons/HelpCircle' +import {timeOptions} from '../outsourceConstants' + +import 'react-datepicker/dist/react-datepicker.css' + +const DeliverySection = ({ + delivery, + errorQuote, + needItFaster, + outsourceConfirmed, + errorPastDate, + quoteNotAvailable, + showDateMessage, + deliveryDate, + selectedTime, + onChangeTimezone, + onToggleNeedItFaster, + onDateChange, + onTimeChange, + onGetNewRates, + extendedView, +}) => { + if (errorQuote) { + return ( +
    +
    + Quote not available, please contact us at info@translated.net or call + +39 06 90 254 001 +
    +
    + ) + } + + if (needItFaster) { + return ( +
    +
    +
    + + +
    +
    + + +
    +
    + {!outsourceConfirmed && ( +
    + + {priceCurrencySymbol}{' '} + {formatWithCommas(getCurrencyPrice(revisionPrice))} +
    + )} +
    + ) +} + +export default RevisionCheckbox diff --git a/public/js/components/outsource/components/ServiceBox.js b/public/js/components/outsource/components/ServiceBox.js new file mode 100644 index 0000000000..cb05698a8a --- /dev/null +++ b/public/js/components/outsource/components/ServiceBox.js @@ -0,0 +1,21 @@ +import React from 'react' +import TranslatedIcon from '../../../../img/icons/TranslatedIcon' + +const ServiceBox = ({revision, compact = false}) => ( +
    +
    +
    Outsource:
    +
    Project Management + Translation
    + {(revision || compact) &&
    + Revision
    } +
    + {!compact && ( +
    + Guaranteed by + + Translated +
    + )} +
    +) + +export default ServiceBox diff --git a/public/js/components/outsource/components/TranslatorDetails.js b/public/js/components/outsource/components/TranslatorDetails.js new file mode 100644 index 0000000000..bc3d15e151 --- /dev/null +++ b/public/js/components/outsource/components/TranslatorDetails.js @@ -0,0 +1,67 @@ +import React from 'react' +import {formatWithCommas} from '../outsourceConstants' +import ChevronRight from '../../../../img/icons/ChevronRight' + +const TranslatorDetails = ({ + chunkQuote, + translatedWords, + job, + outsourceConfirmed, + priceCurrencySymbol, + getCurrencyPrice, +}) => ( + <> + {chunkQuote.get('t_name') !== '' && ( +
    + Best identified translator for this job: +
    + )} + +
    + {chunkQuote.get('t_name') !== '' ? ( + <> +
    +
    + {chunkQuote.get('t_name').charAt(0)} +
    +
    +
    + {chunkQuote.get('t_name')} by Translated +
    +
    + {translatedWords} words translated last 12 months +
    +
    + {chunkQuote.get('t_experience_years')} years of experience +
    +
    +
    + + ) : ( +
    +

    + Translated uses the most qualified translator
    and{' '} + keeps using the same translator for your next projects. +

    +
    + )} + +
    + {job.get('source')} + + {job.get('target')} +
    +
    + {formatWithCommas(chunkQuote.get('words'))} words +
    + {!outsourceConfirmed && ( +
    + {priceCurrencySymbol}{' '} + {formatWithCommas(getCurrencyPrice(chunkQuote.get('price')))} +
    + )} +
    + +) + +export default TranslatorDetails diff --git a/public/js/components/outsource/outsourceConstants.js b/public/js/components/outsource/outsourceConstants.js new file mode 100644 index 0000000000..db401b9838 --- /dev/null +++ b/public/js/components/outsource/outsourceConstants.js @@ -0,0 +1,41 @@ +// Note 2024-07-08 +// I temporary removed RUB and TRY because the Translated API +// does not return the corresponding conversion rates +export const currencies = { + EUR: {symbol: '€', name: 'Euro (EUR)'}, + USD: {symbol: 'US$', name: 'US dollar (USD)'}, + AUD: {symbol: '$', name: 'Australian dollar (AUD)'}, + CAD: {symbol: '$', name: 'Canadian dollar (CAD)'}, + NZD: {symbol: '$', name: 'New Zealand dollar (NZD)'}, + GBP: {symbol: '£', name: 'Pound sterling (GBP)'}, + BRL: {symbol: 'R$', name: 'Real (BRL)'}, + //RUB: {symbol: 'руб', name: 'Russian ruble (RUB)'}, + SEK: {symbol: 'kr', name: 'Swedish krona (SEK)'}, + CHF: {symbol: 'Fr.', name: 'Swiss franc (CHF)'}, + //TRY: {symbol: 'TL', name: 'Turkish lira (TL)'}, + KRW: {symbol: '₩', name: 'Won (KRW)'}, + JPY: {symbol: '¥', name: 'Yen (JPY)'}, + PLN: {symbol: 'zł', name: 'Złoty (PLN)'}, +} + +export const timeOptions = [ + {name: '7:00 AM', id: '7'}, + {name: '8:00 AM', id: '8'}, + {name: '9:00 AM', id: '9'}, + {name: '10:00 AM', id: '10'}, + {name: '11:00 AM', id: '11'}, + {name: '12:00 PM', id: '12'}, + {name: '1:00 PM', id: '13'}, + {name: '2:00 PM', id: '14'}, + {name: '3:00 PM', id: '15'}, + {name: '4:00 PM', id: '16'}, + {name: '5:00 PM', id: '17'}, + {name: '6:00 PM', id: '18'}, + {name: '7:00 PM', id: '19'}, + {name: '8:00 PM', id: '20'}, + {name: '9:00 PM', id: '21'}, +] + +export const formatWithCommas = (value) => + String(value).replace(/\B(?=(\d{3})+(?!\d))/g, ',') + diff --git a/public/js/components/projects/ChunksJobContainer.js b/public/js/components/projects/ChunksJobContainer.js new file mode 100644 index 0000000000..49e5cf68fa --- /dev/null +++ b/public/js/components/projects/ChunksJobContainer.js @@ -0,0 +1,274 @@ +import PropTypes from 'prop-types' +import React, {useEffect, useMemo, useRef, useState} from 'react' +import {JobContainer} from './JobContainer' +import {Checkbox, CHECKBOX_STATE} from '../common/Checkbox' +import IconDown from '../icons/IconDown' +import JobMenu from './JobMenu' +import Download from '../../../img/icons/Download' +import CommonUtils from '../../utils/commonUtils' +import ModalsActions from '../../actions/ModalsActions' +import ManageActions from '../../actions/ManageActions' +import CatToolActions from '../../actions/CatToolActions' +import ConfirmMessageModal from '../modals/ConfirmMessageModal' +import Tooltip from '../common/Tooltip' +import ProjectsStore from '../../stores/ProjectsStore' +import ManageConstants from '../../constants/ManageConstants' + +export const ChunksJobContainer = ({chunks, ...props}) => { + const [showDownloadProgress, setShowDownloadProgress] = useState(false) + + const sourceTargetTextRef = useRef() + + const job = useMemo(() => chunks[0], [chunks]) + + const {project} = props + + useEffect(() => { + const disableDownloadMenu = (idJob) => { + if (job.get('id') === idJob) { + setShowDownloadProgress(true) + } + } + + const enableDownloadMenu = (idJob) => { + if (job.get('id') === idJob) { + setShowDownloadProgress(false) + } + } + + ProjectsStore.addListener( + ManageConstants.ENABLE_DOWNLOAD_BUTTON, + enableDownloadMenu, + ) + ProjectsStore.addListener( + ManageConstants.DISABLE_DOWNLOAD_BUTTON, + disableDownloadMenu, + ) + + return () => { + ProjectsStore.removeListener( + ManageConstants.ENABLE_DOWNLOAD_BUTTON, + enableDownloadMenu, + ) + ProjectsStore.removeListener( + ManageConstants.DISABLE_DOWNLOAD_BUTTON, + disableDownloadMenu, + ) + } + }, [job]) + + const getTranslateUrl = () => { + return ( + '/translate/' + + project.get('project_slug') + + '/' + + job.get('source') + + '-' + + job.get('target') + + '/' + + job.get('password') + ) + } + + const downloadTranslation = () => { + const url = getTranslateUrl() + '?action=warnings' + props.downloadTranslationFn(project.toJS(), job.toJS(), url) + } + + const getDownloadLabel = () => { + const stats = job.get('stats').toJS() + const jobTranslated = stats.raw.draft === 0 && stats.raw.new === 0 + const remoteService = props.project.get('remote_file_service') + let label = ( + <> + Draft + + ) + let action = () => { + const data = { + event: 'download_draft', + } + CommonUtils.dispatchAnalyticsEvents(data) + downloadTranslation() + } + if (jobTranslated && !remoteService) { + label = ( + <> + Download Translation + + ) + action = downloadTranslation + } else if (jobTranslated && remoteService === 'gdrive') { + label = ( + <> + Open in Google Drive + + ) + action = downloadTranslation + } else if (remoteService && remoteService === 'gdrive') { + label = ( + <> + Preview in Google Drive + + ) + action = downloadTranslation + } + return {label, action} + } + + const openMergeModal = () => { + ModalsActions.openMergeModal( + project.toJS(), + job.toJS(), + ManageActions.reloadProjects, + ) + } + + const archiveJob = () => { + ManageActions.changeJobStatus(project, job, 'archive') + if (project.get('jobs').size > 1) { + CatToolActions.addNotification({ + title: `Jobs archived`, + text: `The selected jobs has been successfully archived.`, + type: 'warning', + position: 'bl', + allowHtml: true, + timer: 10000, + }) + } + } + + const activateJob = () => { + ManageActions.changeJobStatus(project, job, 'active') + if (project.get('jobs').size > 1) { + CatToolActions.addNotification({ + title: `Jobs unarchived`, + text: `The selected jobs has been successfully unarchived.`, + type: 'warning', + position: 'bl', + allowHtml: true, + timer: 10000, + }) + } + } + + const cancelJob = () => { + ManageActions.changeJobStatus(project, job, 'cancel') + if (project.get('jobs').size > 1) { + CatToolActions.addNotification({ + title: `Jobs canceled`, + text: `The selected jobs has been successfully canceled.`, + type: 'warning', + position: 'bl', + allowHtml: true, + timer: 10000, + }) + } + } + + const deleteJob = () => { + const props = { + text: + 'You are about to delete this job permanently. This action cannot be undone.
    ' + + ' Are you sure you want to proceed?', + successText: 'Yes, delete it', + successCallback: () => { + ManageActions.changeJobStatus(project, job, 'delete') + if (project.get('jobs').size > 1) { + CatToolActions.addNotification({ + title: `Jobs deleted permanently`, + text: `The selected jobs has been successfully deleted permanently.`, + type: 'warning', + position: 'bl', + allowHtml: true, + timer: 10000, + }) + } + }, + cancelCallback: () => {}, + } + ModalsActions.showModalComponent( + ConfirmMessageModal, + props, + 'Confirmation required', + ) + } + + const getJobMenu = () => { + const jobTMXUrl = '/api/v2/tmx/' + job.get('id') + '/' + job.get('password') + const exportXliffUrl = + '/api/v2/xliff/' + + job.get('id') + + '/' + + job.get('password') + + '/' + + props.project.get('project_slug') + + '.zip' + + const originalUrl = `/api/v2/original/${job.get('id')}/${job.get('password')}` + + return ( + + ) + } + + return ( +
    +
    +
    + props.onCheckedJob(job.get('id'))} + value={ + props.isChecked + ? CHECKBOX_STATE.CHECKED + : CHECKBOX_STATE.UNCHECKED + } + /> + + + {job.get('source')} + + {job.get('target')} + + +
    +
    {getJobMenu()}
    +
    +
    + {chunks.map((job, index) => ( + + ))} +
    +
    + ) +} + +ChunksJobContainer.propTypes = { + chunks: PropTypes.array.isRequired, +} diff --git a/public/js/components/projects/JobContainer.js b/public/js/components/projects/JobContainer.js index 0df1bc65f1..9e03a57156 100644 --- a/public/js/components/projects/JobContainer.js +++ b/public/js/components/projects/JobContainer.js @@ -1,188 +1,216 @@ -import React, {useRef} from 'react' -import $ from 'jquery' +import PropTypes from 'prop-types' +import React, {useEffect, useRef, useState} from 'react' +import {Checkbox, CHECKBOX_STATE} from '../common/Checkbox' import JobMenu from './JobMenu' -import OutsourceContainer from '../outsource/OutsourceContainer' +import Download from '../../../img/icons/Download' import CommonUtils from '../../utils/commonUtils' -import ManageActions from '../../actions/ManageActions' import ModalsActions from '../../actions/ModalsActions' -import ManageConstants from '../../constants/ManageConstants' -import ProjectsStore from '../../stores/ProjectsStore' +import ManageActions from '../../actions/ManageActions' import {changeJobPassword} from '../../api/changeJobPassword' import CatToolActions from '../../actions/CatToolActions' import ConfirmMessageModal from '../modals/ConfirmMessageModal' +import IconDown from '../icons/IconDown' +import { + Button, + BUTTON_MODE, + BUTTON_SIZE, + BUTTON_TYPE, +} from '../common/Button/Button' import TranslatedIconSmall from '../../../img/icons/TranslatedIconSmall' -import Tooltip from '../common/Tooltip' import JobProgressBar from '../common/JobProgressBar' -import {Popup} from 'semantic-ui-react' -import {DropdownMenu} from '../common/DropdownMenu/DropdownMenu' -import {BUTTON_SIZE} from '../common/Button/Button' -import {Checkbox, CHECKBOX_STATE} from '../common/Checkbox' -import Download from '../../../img/icons/Download' +import Tooltip from '../common/Tooltip' import QR from '../../../img/icons/QR' -import InfoIcon from '../../../img/icons/InfoIcon' import AlertIcon from '../../../img/icons/AlertIcon' import CommentsIcon from '../../../img/icons/CommentsIcon' - -class JobContainer extends React.Component { - constructor(props) { - super(props) - this.state = { - showDownloadProgress: false, - openOutsource: false, - showTranslatorBox: false, - extendedView: true, +import ProjectsStore from '../../stores/ProjectsStore' +import ManageConstants from '../../constants/ManageConstants' +import OutsourceContainer from '../outsource/OutsourceContainer' +import {fromJS} from 'immutable' +import Close from '../../../img/icons/Close' + +export const JobContainer = ({ + job, + project, + isChunk, + isChecked, + isChunkOutsourced, + onCheckedJob, + downloadTranslationFn, + index, +}) => { + const [showDownloadProgress, setShowDownloadProgress] = useState(false) + const [showingOutsource, setShowingOutsource] = useState() + + const qrIconRef = useRef() + const warningsIconRef = useRef() + const commentsIconRef = useRef() + const sourceTargetTextRef = useRef() + const deliveryEmailRef = useRef() + const deliveryDateRef = useRef() + + useEffect(() => { + const disableDownloadMenu = (idJob) => { + if (job.get('id') === idJob) { + setShowDownloadProgress(true) + } } - this.getTranslateUrl = this.getTranslateUrl.bind(this) - this.getAnalysisUrl = this.getAnalysisUrl.bind(this) - this.changePassword = this.changePassword.bind(this) - this.removeTranslator = this.removeTranslator.bind(this) - this.downloadTranslation = this.downloadTranslation.bind(this) - this.openMergeModal = this.openMergeModal.bind(this) - this.openSplitModal = this.openSplitModal.bind(this) - this.archiveJob = this.archiveJob.bind(this) - this.activateJob = this.activateJob.bind(this) - this.cancelJob = this.cancelJob.bind(this) - this.deleteJob = this.deleteJob.bind(this) - } + const enableDownloadMenu = (idJob) => { + if (job.get('id') === idJob) { + setShowDownloadProgress(false) + } + } - getTranslateUrl() { - let use_prefix = this.props.jobsLenght > 1 - let chunk_id = - this.props.job.get('id') + (use_prefix ? '-' + this.props.index : '') - return ( - '/translate/' + - this.props.project.get('project_slug') + - '/' + - this.props.job.get('source') + - '-' + - this.props.job.get('target') + - '/' + - chunk_id + - '-' + - this.props.job.get('password') + - (use_prefix ? '#' + this.props.job.get('job_first_segment') : '') + ProjectsStore.addListener( + ManageConstants.ENABLE_DOWNLOAD_BUTTON, + enableDownloadMenu, ) - } - - getReviseUrl() { - let use_prefix = this.props.jobsLenght > 1 - let chunk_id = - this.props.job.get('id') + (use_prefix ? '-' + this.props.index : '') - let possibly_different_review_password = this.props.job.has( - 'revise_passwords', + ProjectsStore.addListener( + ManageConstants.DISABLE_DOWNLOAD_BUTTON, + disableDownloadMenu, ) - ? this.props.job.get('revise_passwords').get(0).get('password') - : this.props.job.get('password') + + return () => { + ProjectsStore.removeListener( + ManageConstants.ENABLE_DOWNLOAD_BUTTON, + enableDownloadMenu, + ) + ProjectsStore.removeListener( + ManageConstants.DISABLE_DOWNLOAD_BUTTON, + disableDownloadMenu, + ) + } + }, [job]) + + const idJobLabel = !isChunk ? job.get('id') : job.get('id') + '-' + index + + const getReviseUrl = () => { + const use_prefix = project.get('jobs').size > 1 && isChunk + const chunk_id = job.get('id') + (use_prefix ? '-' + index : '') + const possibly_different_review_password = job.has('revise_passwords') + ? job.get('revise_passwords').get(0).get('password') + : job.get('password') return ( '/revise/' + - this.props.project.get('project_slug') + + project.get('project_slug') + '/' + - this.props.job.get('source') + + job.get('source') + '-' + - this.props.job.get('target') + + job.get('target') + '/' + chunk_id + '-' + possibly_different_review_password + - (use_prefix ? '#' + this.props.job.get('job_first_segment') : '') + (use_prefix ? '#' + job.get('job_first_segment') : '') ) } - getEditingLogUrl() { - return ( - '/editlog/' + - this.props.job.get('id') + - '-' + - this.props.job.get('password') - ) + const getEditingLogUrl = () => { + return '/editlog/' + job.get('id') + '-' + job.get('password') } - getQAReport() { + const getQAReport = () => { if ( - this.props.project.get('features') && - this.props.project.get('features').indexOf('review_improved') > -1 + project.get('features') && + project.get('features').indexOf('review_improved') > -1 ) { return ( '/plugins/review_improved/quality_report/' + - this.props.job.get('id') + + job.get('id') + '/' + - this.props.job.get('password') + job.get('password') ) } else { - return ( - '/revise-summary/' + - this.props.job.get('id') + - '-' + - this.props.job.get('password') + return '/revise-summary/' + job.get('id') + '-' + job.get('password') + } + } + + const downloadTranslation = () => { + const url = getTranslateUrl() + '?action=warnings' + downloadTranslationFn(project.toJS(), job.toJS(), url) + } + + const getDownloadLabel = () => { + const stats = job.get('stats').toJS() + const jobTranslated = stats.raw.draft === 0 && stats.raw.new === 0 + const remoteService = project.get('remote_file_service') + let label = ( + <> + Draft + + ) + let action = () => { + const data = { + event: 'download_draft', + } + CommonUtils.dispatchAnalyticsEvents(data) + downloadTranslation() + } + if (jobTranslated && !remoteService) { + label = ( + <> + Download Translation + + ) + action = downloadTranslation + } else if (jobTranslated && remoteService === 'gdrive') { + label = ( + <> + Open in Google Drive + + ) + action = downloadTranslation + } else if (remoteService && remoteService === 'gdrive') { + label = ( + <> + Preview in Google Drive + ) + action = downloadTranslation } + return {label, action} + } + + const openSplitModal = () => { + ModalsActions.openSplitJobModal(job, project, ManageActions.reloadProjects) } - changePassword(revision_number) { - let self = this - let label = '' + const openMergeModal = () => { + ModalsActions.openMergeModal( + project.toJS(), + job.toJS(), + ManageActions.reloadProjects, + ) + } + + const changePassword = (revision_number) => { + let oldPassword + switch (revision_number) { case undefined: { - this.oldPassword = this.props.job.get('password') - label = 'Translate' + oldPassword = job.get('password') break } case 1: { - this.oldPassword = this.props.job - .get('revise_passwords') - .get(0) - .get('password') - label = 'Revise' + oldPassword = job.get('revise_passwords').get(0).get('password') break } case 2: { - this.oldPassword = this.props.job - .get('revise_passwords') - .get(1) - .get('password') - label = 'Revise 2' + oldPassword = job.get('revise_passwords').get(1).get('password') break } } - changeJobPassword( - this.props.job.toJS(), - this.oldPassword, - revision_number, - ).then(function (data) { - const notification = { - uid: 'change-password', - title: revision_number - ? `${revision_number === 1 ? 'Revise' : 'Revise 2'} password changed` - : 'Translate password changed', - text: revision_number - ? `The ${revision_number === 1 ? 'Revise' : 'Revise 2'} password has been changed. Undo` - : 'The Translate password has been changed. Undo', - type: 'warning', - position: 'bl', - allowHtml: true, - timer: 10000, - } - CatToolActions.addNotification(notification) - let translator = self.props.job.get('translator') - ManageActions.changeJobPassword( - self.props.project, - self.props.job, - data.new_pwd, - data.old_pwd, - revision_number, - ) - setTimeout(function () { - $('.undo-password').off('click') - $('.undo-password').on('click', function () { + changeJobPassword(job.toJS(), oldPassword, revision_number).then( + function (data) { + const onClickUndo = () => { CatToolActions.removeNotification(notification) changeJobPassword( - self.props.job.toJS(), + job.toJS(), data.new_pwd, revision_number, 1, - self.oldPassword, + oldPassword, ).then(function (data) { const restoreNotification = { title: 'Change job password', @@ -193,139 +221,107 @@ class JobContainer extends React.Component { } CatToolActions.addNotification(restoreNotification) ManageActions.changeJobPassword( - self.props.project, - self.props.job, + project, + job, data.new_pwd, data.old_pwd, revision_number, translator, ) }) - }) - }, 500) - }) - } + } - removeTranslator() { - let self = this - this.oldPassword = this.props.job.get('password') - changeJobPassword(this.props.job.toJS(), this.oldPassword).then( - function (data) { const notification = { - uid: 'remove-translator', - title: 'Job unassigned', - text: 'The translator has been removed and the password changed. Undo', + uid: 'change-password', + title: revision_number + ? `${revision_number === 1 ? 'Revise' : 'Revise 2'} password changed` + : 'Translate password changed', + text: revision_number ? ( + <> + The {revision_number === 1 ? 'Revise' : 'Revise 2'} password has + been changed.{' '} + + Undo + + + ) : ( + <> + The Translate password has been changed.{' '} + + Undo + + + ), type: 'warning', position: 'bl', - allowHtml: true, timer: 10000, } CatToolActions.addNotification(notification) - let translator = self.props.job.get('translator') + let translator = job.get('translator') ManageActions.changeJobPassword( - self.props.project, - self.props.job, + project, + job, data.new_pwd, data.old_pwd, - null, - null, + revision_number, ) - setTimeout(function () { - $('.undo-password').off('click') - $('.undo-password').on('click', function () { - CatToolActions.removeNotification(notification) - changeJobPassword( - self.props.job.toJS(), - data.new_pwd, - null, - 1, - self.oldPassword, - ).then(function (data) { - const passwordNotification = { - uid: 'change-password', - title: 'Change job password', - text: 'The previous password has been restored.', - type: 'warning', - position: 'bl', - timer: 7000, - } - CatToolActions.addNotification(passwordNotification) - ManageActions.changeJobPassword( - self.props.project, - self.props.job, - data.new_pwd, - data.old_pwd, - null, - translator, - ) - }) - }) - }, 500) }, ) } - archiveJob() { - ManageActions.changeJobStatus(this.props.project, this.props.job, 'archive') - if (this.props.project.get('jobs').size > 1) { + const archiveJob = () => { + ManageActions.changeJobStatus(project, job, 'archive') + if (project.get('jobs').size > 1) { CatToolActions.addNotification({ title: `Jobs archived`, text: `The selected jobs has been successfully archived.`, type: 'warning', position: 'bl', - allowHtml: true, timer: 10000, }) } } - cancelJob() { - ManageActions.changeJobStatus(this.props.project, this.props.job, 'cancel') - if (this.props.project.get('jobs').size > 1) { + const activateJob = () => { + ManageActions.changeJobStatus(project, job, 'active') + if (project.get('jobs').size > 1) { CatToolActions.addNotification({ - title: `Jobs canceled`, - text: `The selected jobs has been successfully canceled.`, + title: `Jobs unarchived`, + text: `The selected jobs has been successfully unarchived.`, type: 'warning', position: 'bl', - allowHtml: true, timer: 10000, }) } } - activateJob() { - ManageActions.changeJobStatus(this.props.project, this.props.job, 'active') - if (this.props.project.get('jobs').size > 1) { + const cancelJob = () => { + ManageActions.changeJobStatus(project, job, 'cancel') + if (project.get('jobs').size > 1) { CatToolActions.addNotification({ - title: `Jobs unarchived`, - text: `The selected jobs has been successfully unarchived.`, + title: `Jobs canceled`, + text: `The selected jobs has been successfully canceled.`, type: 'warning', position: 'bl', - allowHtml: true, timer: 10000, }) } } - deleteJob() { + const deleteJob = () => { const props = { text: 'You are about to delete this job permanently. This action cannot be undone.
    ' + ' Are you sure you want to proceed?', successText: 'Yes, delete it', successCallback: () => { - ManageActions.changeJobStatus( - this.props.project, - this.props.job, - 'delete', - ) - if (this.props.project.get('jobs').size > 1) { + ManageActions.changeJobStatus(project, job, 'delete') + if (project.get('jobs').size > 1) { CatToolActions.addNotification({ title: `Jobs deleted permanently`, text: `The selected jobs has been successfully deleted permanently.`, type: 'warning', position: 'bl', - allowHtml: true, timer: 10000, }) } @@ -339,311 +335,249 @@ class JobContainer extends React.Component { ) } - downloadTranslation() { - let url = this.getTranslateUrl() + '?action=warnings' - this.props.downloadTranslationFn( - this.props.project.toJS(), - this.props.job.toJS(), - url, - ) - } - - disableDownloadMenu(idJob) { - if (this.props.job.get('id') === idJob) { - this.setState({ - showDownloadProgress: true, - }) - } - } + const removeTranslator = () => { + let oldPassword = job.get('password') + changeJobPassword(job.toJS(), oldPassword).then(function (data) { + const onClickUndo = () => { + CatToolActions.removeNotification(notification) + changeJobPassword(job.toJS(), data.new_pwd, null, 1, oldPassword).then( + function (data) { + const passwordNotification = { + uid: 'change-password', + title: 'Change job password', + text: 'The previous password has been restored.', + type: 'warning', + position: 'bl', + timer: 7000, + } + CatToolActions.addNotification(passwordNotification) + ManageActions.changeJobPassword( + project, + job, + data.new_pwd, + data.old_pwd, + null, + translator, + ) + }, + ) + } - enableDownloadMenu(idJob) { - if (this.props.job.get('id') === idJob) { - this.setState({ - showDownloadProgress: false, - }) - } + const notification = { + uid: 'remove-translator', + title: 'Job unassigned', + text: ( + <> + The translator has been removed and the password changed.{' '} + + Undo + + + ), + type: 'warning', + position: 'bl', + timer: 10000, + } + CatToolActions.addNotification(notification) + let translator = job.get('translator') + ManageActions.changeJobPassword( + project, + job, + data.new_pwd, + data.old_pwd, + null, + null, + ) + }) } - openSplitModal() { - ModalsActions.openSplitJobModal( - this.props.job, - this.props.project, - ManageActions.reloadProjects, + const getTranslateUrl = () => { + const use_prefix = project.get('jobs').size > 1 && isChunk + const chunk_id = job.get('id') + (use_prefix ? '-' + index : '') + return ( + '/translate/' + + project.get('project_slug') + + '/' + + job.get('source') + + '-' + + job.get('target') + + '/' + + chunk_id + + '-' + + job.get('password') + + (use_prefix ? '#' + job.get('job_first_segment') : '') ) } - openMergeModal() { - ModalsActions.openMergeModal( - this.props.project.toJS(), - this.props.job.toJS(), - ManageActions.reloadProjects, + const getProjectAnalyzeUrl = () => { + return ( + '/analyze/' + + project.get('project_slug') + + '/' + + project.get('id') + + '-' + + project.get('password') ) } - getDownloadLabel() { - const stats = this.props.job.get('stats').toJS() - let jobTranslated = stats.raw.draft === 0 && stats.raw.new === 0 - let remoteService = this.props.project.get('remote_file_service') - let label = ( - <> - Draft - - ) - let action = () => { - const data = { - event: 'download_draft', - } - CommonUtils.dispatchAnalyticsEvents(data) - this.downloadTranslation() - } - if (jobTranslated && !remoteService) { - label = ( - <> - Download Translation - - ) - action = this.downloadTranslation - } else if (jobTranslated && remoteService === 'gdrive') { - label = ( - <> - Open in Google Drive - - ) - action = this.downloadTranslation - } else if (remoteService && remoteService === 'gdrive') { - label = ( - <> - Preview in Google Drive - - ) - action = this.downloadTranslation - } - return {label, action} - } - - getJobMenu() { - let jobTMXUrl = - '/api/v2/tmx/' + - this.props.job.get('id') + - '/' + - this.props.job.get('password') - let exportXliffUrl = + const getJobMenu = () => { + const jobTMXUrl = '/api/v2/tmx/' + job.get('id') + '/' + job.get('password') + const exportXliffUrl = '/api/v2/xliff/' + - this.props.job.get('id') + + job.get('id') + '/' + - this.props.job.get('password') + + job.get('password') + '/' + - this.props.project.get('project_slug') + + project.get('project_slug') + '.zip' - let originalUrl = `/api/v2/original/${this.props.job.get('id')}/${this.props.job.get('password')}` + const originalUrl = `/api/v2/original/${job.get('id')}/${job.get('password')}` + return ( ) } - getAnalysisUrl() { - return ( - '/jobanalysis/' + - this.props.project.get('id') + - '-' + - this.props.job.get('id') + - '-' + - this.props.job.get('password') - ) - } - - getProjectAnalyzeUrl() { - return ( - '/analyze/' + - this.props.project.get('project_slug') + - '/' + - this.props.project.get('id') + - '-' + - this.props.project.get('password') - ) - } - - openTMPanel() { - ManageActions.openJobTMPanel( - this.props.job.toJS(), - this.props.project.get('project_slug'), - ) - } - - getCommentsIcon() { - let icon = '' - let openThreads = this.props.job.get('open_threads_count') - if (openThreads > 0) { - let tooltipText = '' - if (this.props.job.get('open_threads_count') === 1) { - tooltipText = 'There is an open thread' - } else { - tooltipText = - 'There are ' + - openThreads + - ' open threads' + const openOutsourceModal = (showTranslatorBox, extendedView) => { + if ( + (showTranslatorBox && !job.get('outsource_available')) || + job.get('outsource_available') + ) { + if ( + job.get('outsource_available') && + typeof showingOutsource !== 'undefined' + ) { + const data = { + event: 'outsource_request', + } + CommonUtils.dispatchAnalyticsEvents(data) } - var translatedUrl = this.getTranslateUrl() + '?action=openComments' - icon = ( -
    - - - - } - /> -
    - ) + setShowingOutsource({showTranslatorBox, extendedView}) + } else { + window.open('https://translated.com/contact-us', '_blank') } - return icon } - getQRIcon() { - var icon = '' - var quality = this.props.job.get('quality_summary').get('quality_overall') + const closeOutsourceModal = () => setShowingOutsource() + + const getQRIcon = () => { + const quality = job.get('quality_summary').get('quality_overall') if (quality === 'poor' || quality === 'fail') { - var url = this.getQAReport() - let tooltipText = 'Overall quality: ' + quality.toUpperCase() - var classQuality = quality === 'poor' ? 'yellow' : 'red' - icon = ( -
    - - - - } - /> -
    + const url = getQAReport() + const tooltipText = 'Overall quality: ' + quality?.toUpperCase() + const classQuality = quality === 'poor' ? 'yellow' : 'red' + return ( + + + ) } - return icon } - getWarningsIcon() { - var icon = '' - var warnings = this.props.job.get('warnings_count') + const getWarningsIcon = () => { + const warnings = job.get('warnings_count') if (warnings > 0) { - var url = this.getTranslateUrl() + '?action=warnings' + const url = getTranslateUrl() + '?action=warnings' let tooltipText = 'Click to see issues' - icon = ( -
    - - - - } - /> -
    + return ( + + + ) } - return icon } - openOutsourceModal = (showTranslatorBox, extendedView) => { - if (showTranslatorBox && !this.props.job.get('outsource_available')) { - this.setState({ - showTranslatorBox: showTranslatorBox, - extendedView: false, - }) - } else if (this.props.job.get('outsource_available')) { - if (!this.state.openOutsource) { - const data = { - event: 'outsource_request', - } - CommonUtils.dispatchAnalyticsEvents(data) - } - this.setState({ - openOutsource: true, - showTranslatorBox: showTranslatorBox, - extendedView: extendedView, - }) - } else { - window.open('https://translated.com/contact-us', '_blank') + const getCommentsIcon = () => { + const openThreads = job.get('open_threads_count') + if (openThreads > 0) { + const tooltipText = + job.get('open_threads_count') === 1 + ? 'There is an open thread' + : `There are ${openThreads} open threads` + + var translatedUrl = getTranslateUrl() + '?action=openComments' + return ( + + + + ) } } - closeOutsourceModal() { - this.setState({ - openOutsource: false, - showTranslatorBox: false, - extendedView: false, - }) - } + const getWarningsGroup = () => { + const iconsBody = ( + <> + {getQRIcon()} + {getWarningsIcon()} + {getCommentsIcon()} + + ) - getOutsourceButton() { return ( - +
    + {iconsBody} +
    ) } - getOutsourceJobSent() { - let outsourceJobLabel = '' - if (this.props.job.get('outsource')) { - if (this.props.job.get('outsource').get('id_vendor') == '1') { - outsourceJobLabel = ( + const getOutsourceJobSent = () => { + let outsourceJobElement = '' + if (job.get('outsource')) { + if (job.get('outsource').get('id_vendor') == '1') { + outsourceJobElement = ( Translated logo ) } - } else if (this.props.job.get('translator')) { - outsourceJobLabel = undefined + } else if (job.get('translator')) { + outsourceJobElement = undefined } else { - outsourceJobLabel = ( - + outsourceJobElement = ( + ) } - return outsourceJobLabel + return outsourceJobElement } - getOutsourceDelivery() { + const getOutsourceDelivery = () => { const gmtDate = - this.props.job.get('outsource') && - this.props.job.get('outsource').get('id_vendor') == '1' + job.get('outsource') && job.get('outsource').get('id_vendor') == '1' ? CommonUtils.getGMTDate( - this.props.job.get('outsource').get('delivery_timestamp') * 1000, + job.get('outsource').get('delivery_timestamp') * 1000, ) - : this.props.job.get('translator') && + : job.get('translator') && CommonUtils.getGMTDate( - this.props.job.get('translator').get('delivery_timestamp') * 1000, + job.get('translator').get('delivery_timestamp') * 1000, ) return ( gmtDate && (
    - - {this.props.job.get('translator') && ( - - {this.props.job.get('translator').get('email')} - +
    + {job.get('translator') && ( + +
    openOutsourceModal(true, false)} + > + {job.get('translator').get('email')} +
    +
    )}{' '} - - {gmtDate.day} {gmtDate.month} {gmtDate.time} - {' '} - {gmtDate.gmt} - + + + {gmtDate.day} {gmtDate.month} - {gmtDate.time} + + + {job.get('translator') && ( + + )} +
    ) ) } - getOutsourceDeliveryPrice() { - let outsourceDeliveryPrice = '' - if (this.props.job.get('outsource')) { - if (this.props.job.get('outsource').get('id_vendor') == '1') { - let price = this.props.job.get('outsource').get('price') - outsourceDeliveryPrice = ( -
    - - {this.props.job.get('outsource').get('currency')}{' '} - - {price} -
    + const getOutsourceButton = () => { + if (!config.enable_outsource) return + + const outsourceInfo = job.get('outsource_info') + ? job.get('outsource_info').toJS() + : undefined + let label = + !job.get('outsource_available') && outsourceInfo?.custom_payable_rate ? ( +
    + +
    + ) : ( +
    + +
    + ) + if (job.get('outsource')) { + if (job.get('outsource').get('id_vendor') == '1') { + label = ( + ) } } - return outsourceDeliveryPrice - } - - getWarningsInfo() { - let n = { - number: 0, - icon: '', - } - let quality = this.props.job.get('quality_summary').get('quality_overall') - if ((quality && quality === 'poor') || quality === 'fail') { - n.number++ - n.icon = this.getQRIcon() - } - if ( - this.props.job.get('open_threads_count') && - this.props.job.get('open_threads_count') > 0 - ) { - n.number++ - n.icon = this.getCommentsIcon() - } - if ( - this.props.job.get('warnings_count') && - this.props.job.get('warnings_count') > 0 - ) { - n.number++ - n.icon = this.getWarningsIcon() - } - return n - } - - getWarningsGroup() { - const iconsBody = ( - <> - {this.getQRIcon()} - {this.getWarningsIcon()} - {this.getCommentsIcon()} - - ) - - return ( -
    - {iconsBody} -
    - ) - } - - shouldComponentUpdate(nextProps, nextState) { - if ( - !nextProps.job.equals(this.props.job) || - nextState.showDownloadProgress !== this.state.showDownloadProgress || - nextState.openOutsource !== this.state.openOutsource || - nextState.showTranslatorBox !== this.state.showTranslatorBox - ) { - this.updated = true - } - return ( - !nextProps.job.equals(this.props.job) || - nextProps.lastAction !== this.props.lastAction || - nextState.showDownloadProgress !== this.state.showDownloadProgress || - nextState.openOutsource !== this.state.openOutsource || - nextState.showTranslatorBox !== this.state.showTranslatorBox || - nextProps.isChecked !== this.props.isChecked || - nextProps.isCheckboxVisible !== this.props.isCheckboxVisible - ) + return label } - componentDidUpdate(prevProps, prevState) { - var self = this - if (this.updated) { - this.container.classList.add('updated-job') - setTimeout(function () { - self.container.classList.remove('updated-job') - }, 500) - self.updated = false - } - if (prevState.openOutsource && this.chunkRow) { - setTimeout(function () { - $('.after-open-outsource').removeClass('after-open-outsource') - self.chunkRow.classList.add('after-open-outsource') - }, 400) - } - } + const stats = job.get('stats').toJS() - componentDidMount() { - ProjectsStore.addListener( - ManageConstants.ENABLE_DOWNLOAD_BUTTON, - this.enableDownloadMenu.bind(this), - ) - ProjectsStore.addListener( - ManageConstants.DISABLE_DOWNLOAD_BUTTON, - this.disableDownloadMenu.bind(this), - ) - } - - componentWillUnmount() { - ProjectsStore.removeListener( - ManageConstants.ENABLE_DOWNLOAD_BUTTON, - this.enableDownloadMenu, - ) - ProjectsStore.removeListener( - ManageConstants.DISABLE_DOWNLOAD_BUTTON, - this.disableDownloadMenu, - ) - } - - render() { - let translateUrl = this.getTranslateUrl() - let outsourceButton = this.getOutsourceButton() - let outsourceJobLabel = this.getOutsourceJobSent() - let outsourceDelivery = this.getOutsourceDelivery() - // let outsourceDeliveryPrice = this.getOutsourceDeliveryPrice(); - let analysisUrl = this.getProjectAnalyzeUrl() - let warningIcons = this.getWarningsGroup() - let jobMenu = this.getJobMenu() - let outsourceClass = this.props.job.get('outsource') - ? 'outsource' - : 'translator' - - let idJobLabel = !this.props.isChunk - ? this.props.job.get('id') - : this.props.job.get('id') + '-' + this.props.index - const stats = this.props.job.get('stats').toJS() + return ( +
    +
    + {!isChunk && ( + onCheckedJob(job.get('id'))} + value={ + isChecked ? CHECKBOX_STATE.CHECKED : CHECKBOX_STATE.UNCHECKED + } + /> + )} - return ( -
    -
    (this.container = container)} - > - {!this.state.openOutsource ? ( +
    +
    + {!isChunk && ( + + + {job.get('source')} + + {job.get('target')} + + + )} + ID: {idJobLabel} +
    +
    +
    + +
    +
    + +
    +
    {getWarningsGroup()}
    +
    + {getOutsourceJobSent()} + {getOutsourceDelivery()} + {job.get('translator') && (
    (this.chunkRow = chunkRow)} + className="item" + onClick={removeTranslator} + data-testid="remove-translator-button" > - - this.props.onCheckedJob(this.props.job.get('id')) - } - value={ - this.props.isChecked - ? CHECKBOX_STATE.CHECKED - : CHECKBOX_STATE.UNCHECKED - } - /> -
    - ID: {idJobLabel} -
    - ' + - this.props.job.get('targetTxt') - } - trigger={ -
    -
    - {this.props.job.get('sourceTxt')} -
    -
    - -
    -
    - {this.props.job.get('targetTxt')} -
    -
    - } - /> - - - - {warningIcons} -
    -
    - {outsourceJobLabel} - {outsourceDelivery} - {/*{outsourceDeliveryPrice}*/} - {this.props.job.get('translator') ? ( -
    -
    - -
    -
    - ) : ( - '' - )} -
    +
    +
    - {outsourceButton} - - Open - - {jobMenu} - - {this.state.showDownloadProgress ? ( -
    - ) : ( - '' - )}
    - ) : null} + )} +
    +
    {getOutsourceButton()}
    +
    +
    - +
    {getJobMenu()}
    - ) - } + {typeof showingOutsource !== 'undefined' && ( +
    + +
    + )} +
    + ) } -const OutsourceButton = ({job, openOutsourceModal}) => { - const outsourceButton = useRef() - if (!config.enable_outsource) { - return null - } - const outsourceInfo = job.get('outsource_info') - ? job.get('outsource_info').toJS() - : undefined - let label = - !job.get('outsource_available') && outsourceInfo?.custom_payable_rate ? ( -
    - - Jobs created with custom billing models cannot be outsourced to - Translated. -
    - In order to outsource this job to Translated, please recreate it - using Matecat's standard billing model -
    - } - > -
    - Buy Translation - from - -
    - -
    - ) : ( - - Buy Translation - from - - - ) - if (job.get('outsource')) { - if (job.get('outsource').get('id_vendor') == '1') { - label = ( - - View status - - ) - } - } - return label +JobContainer.propTypes = { + job: PropTypes.object.isRequired, + project: PropTypes.object.isRequired, + isChunk: PropTypes.bool.isRequired, + isChecked: PropTypes.bool.isRequired, + onCheckedJob: PropTypes.func.isRequired, + index: PropTypes.number, } -export default JobContainer diff --git a/public/js/components/projects/JobContainer.test.js b/public/js/components/projects/JobContainer.test.js index cba57aeb9b..ee405934df 100644 --- a/public/js/components/projects/JobContainer.test.js +++ b/public/js/components/projects/JobContainer.test.js @@ -3,7 +3,7 @@ import userEvent from '@testing-library/user-event' import '@testing-library/jest-dom' import React from 'react' import {fromJS} from 'immutable' -import JobContainer from './JobContainer' +import {JobContainer} from './JobContainer' import ProjectsStore from '../../stores/ProjectsStore' import ManageConstants from '../../constants/ManageConstants' @@ -322,7 +322,7 @@ const fakeProjectsData = { }, props: { index: 0, - jobsLenght: 4, + jobsLength: 4, isChunk: false, isChunkOutsourced: false, activityLogUrl: '/activityLog/9/59b94d64a7ef', @@ -492,7 +492,7 @@ const fakeProjectsData = { }, props: { index: 1, - jobsLenght: 2, + jobsLength: 2, isChunk: true, isChunkOutsourced: false, activityLogUrl: '/activityLog/6/59ad778c68b1', @@ -825,7 +825,7 @@ const fakeProjectsData = { }, props: { index: 0, - jobsLenght: 4, + jobsLength: 4, isChunk: false, isChunkOutsourced: false, activityLogUrl: '/activityLog/9/59b94d64a7ef', @@ -865,8 +865,8 @@ const getTranslateUrl = ( ) => { return `/translate/${projectSlug}/${source}-${target}/${chunkId}-${password}${jobFirstSegment}` } -const createTranslateUrl = (index, project, job, jobsLenght) => { - const usePrefix = jobsLenght > 1 +const createTranslateUrl = (index, project, job, jobsLength) => { + const usePrefix = jobsLength > 1 const chunckId = `${job.get('id')}${usePrefix ? '-' + index : ''}` return getTranslateUrl( chunckId, @@ -885,22 +885,16 @@ test('Rendering elements', () => { // ID field expect(screen.getByText(`ID: ${job.get('id')}`)).toBeVisible() - // source field - expect(screen.getByTestId('source-label')).toBeInTheDocument() - - // target field - expect(screen.getByTestId('target-label')).toBeInTheDocument() + expect(screen.getByTestId('source-target-label')).toBeInTheDocument() // words number - expect( - screen.getByText(job.get('stats').get('raw').get('total')), - ).toBeInTheDocument() + expect(screen.getByTestId('words-button')).toBeInTheDocument() // assign job to translator - expect(screen.getByText('Assign job to translator')).toBeInTheDocument() + expect(screen.getByText('Assign')).toBeInTheDocument() // buy translation - expect(screen.getByText('Buy Translation')).toBeInTheDocument() + // expect(screen.getByText('Buy Translation')).toBeInTheDocument() // open expect(screen.getByText(/Open/)).toBeInTheDocument() @@ -923,28 +917,11 @@ test('Check job activity', () => { expect(screen.getByTestId('job-activity-icons')).toBeInTheDocument() }) -test('Job payable: check analisys URL', () => { - const {project, props} = getFakeProperties( - fakeProjectsData.jobWithoutActivity, - ) - render() - - // analysisUrl - const hrefAttribute = screen.getByText('words').getAttribute('href') - - const correctUrl = getProjectAnalyzeUrl( - project.get('project_slug'), - project.get('id'), - project.get('password'), - ) - expect(hrefAttribute).toBe(correctUrl) -}) - test('Assign job to translator: check onClick event', () => { const {props} = getFakeProperties(fakeProjectsData.jobWithoutActivity) render() - const jobToTranslatorElement = screen.getByText('Assign job to translator') + const jobToTranslatorElement = screen.getByText('Assign') expect(jobToTranslatorElement).toBeEnabled() }) @@ -987,7 +964,7 @@ test('Buy translation: check onClick event', () => { expect(buyTranslationElement).toBeEnabled() }) -test('Check Open link', () => { +xtest('Check Open link', () => { const {props, project, job} = getFakeProperties( fakeProjectsData.jobWithoutActivity, ) @@ -999,7 +976,7 @@ test('Check Open link', () => { props.index, project, job, - props.jobsLenght, + props.jobsLength, ) expect(openElement).toBe(correctUrl) }) diff --git a/public/js/components/projects/JobMenu.js b/public/js/components/projects/JobMenu.js index ff0e684473..e2c68abe42 100644 --- a/public/js/components/projects/JobMenu.js +++ b/public/js/components/projects/JobMenu.js @@ -8,62 +8,126 @@ import { import DotsHorizontal from '../../../img/icons/DotsHorizontal' import ChangePassword from '../../../img/icons/ChangePassword' import Archive from '../../../img/icons/Archive' -import Refresh from '../../../img/icons/Refresh' import Trash from '../../../img/icons/Trash' import Split from '../../../img/icons/Split' import Merge from '../../../img/icons/Merge' import Download from '../../../img/icons/Download' import QR from '../../../img/icons/QR' import Revise from '../../../img/icons/Revise' +import {BUTTON_SIZE} from '../common/Button/Button' import FlipBackward from '../icons/FlipBackward' -class JobMenu extends React.Component { - constructor(props) { - super(props) - } +import PropTypes from 'prop-types' - openSecondPassUrl() { - if ( - this.props.job.has('revise_passwords') && - this.props.job.get('revise_passwords').size > 1 - ) { - let url = +const JOB_MENU_ITEM_ID = { + CHANGE_PASSWORD: 'change_password', + SPLIT: 'split', + MERGE: 'merge', + REVISE: 'revise', + REVISE2: 'change_password_revise_2', + QA_REPORT: 'qa_report', + DOWNLOAD: 'download', + ORIGINAL: 'original', + EXPORT_XLIFF: 'export_xliff', + EXPORT_TMX: 'export_tmx', + ARCHIVE: 'archive', + CANCEL: 'cancel', + UNARCHIVE: 'unarchive', + RESUME: 'resume', + DELETE: 'delete', +} + +const JOB_CHUNKS_MENU_ITEM_ID = [ + JOB_MENU_ITEM_ID.MERGE, + JOB_MENU_ITEM_ID.DOWNLOAD, + JOB_MENU_ITEM_ID.ORIGINAL, + JOB_MENU_ITEM_ID.EXPORT_XLIFF, + JOB_MENU_ITEM_ID.EXPORT_TMX, + JOB_MENU_ITEM_ID.ARCHIVE, + JOB_MENU_ITEM_ID.CANCEL, + JOB_MENU_ITEM_ID.UNARCHIVE, + JOB_MENU_ITEM_ID.RESUME, + JOB_MENU_ITEM_ID.DELETE, +] + +const CHUNK_MENU_ITEM_ID = [ + JOB_MENU_ITEM_ID.CHANGE_PASSWORD, + JOB_MENU_ITEM_ID.REVISE, + JOB_MENU_ITEM_ID.REVISE2, + JOB_MENU_ITEM_ID.QA_REPORT, +] + +const JobMenu = ({ + job, + project, + jobId, + status, + qAReportUrl, + jobTMXUrl, + exportXliffUrl, + originalUrl, + reviseUrl, + isChunkOutsourced, + isChunk, + isJobChunks, + changePasswordFn, + openSplitModalFn, + openMergeModalFn, + downloadLabel, + disableDownload, + archiveJobFn, + cancelJobFn, + activateJobFn, + deleteJobFn, +}) => { + const openSecondPassUrl = () => { + if (job.has('revise_passwords') && job.get('revise_passwords').size > 1) { + const url = config.hostpath + '/revise2/' + - this.props.project.get('name') + + project.get('name') + '/' + - this.props.job.get('source') + + job.get('source') + '-' + - this.props.job.get('target') + + job.get('target') + '/' + - this.props.jobId + + jobId + '-' + - this.props.job.get('revise_passwords').get(1).get('password') + job.get('revise_passwords').get(1).get('password') window.open(url) } } - getSecondPassReviewMenuLink() { + const retrieveSecondPassReviewLink = () => { + ManageActions.getSecondPassReview( + project.get('id'), + project.get('password'), + jobId, + job.get('password'), + ).then(() => { + openSecondPassUrl() + }) + } + + const getSecondPassReviewMenuLink = () => { if ( - this.props.project.has('features') && - this.props.project.get('features').indexOf('second_pass_review') > -1 + project.has('features') && + project.get('features').indexOf('second_pass_review') > -1 ) { - if ( - this.props.job.has('revise_passwords') && - this.props.job.get('revise_passwords').size > 1 - ) { - let url = + if (job.has('revise_passwords') && job.get('revise_passwords').size > 1) { + const url = '/revise2/' + - this.props.project.get('name') + + project.get('name') + '/' + - this.props.job.get('source') + + job.get('source') + '-' + - this.props.job.get('target') + + job.get('target') + '/' + - this.props.jobId + + jobId + '-' + - this.props.job.get('revise_passwords').get(1).get('password') + job.get('revise_passwords').get(1).get('password') return [ { + id: JOB_MENU_ITEM_ID.REVISE2, label: ( <> @@ -78,6 +142,7 @@ class JobMenu extends React.Component { } else { return [ { + id: JOB_MENU_ITEM_ID.REVISE2, label: ( <> @@ -85,7 +150,7 @@ class JobMenu extends React.Component { ), onClick: () => { - this.retrieveSecondPassReviewLink() + retrieveSecondPassReviewLink() }, }, ] @@ -94,253 +159,291 @@ class JobMenu extends React.Component { return '' } - retrieveSecondPassReviewLink() { - // event.preventDefault(); - ManageActions.getSecondPassReview( - this.props.project.get('id'), - this.props.project.get('password'), - this.props.jobId, - this.props.job.get('password'), - ).then(() => { - this.openSecondPassUrl() - }) - } - - render() { - let qaReportUrl = this.props.qAReportUrl - let jobTMXUrl = this.props.jobTMXUrl - let exportXliffUrl = this.props.exportXliffUrl - - let originalUrl = this.props.originalUrl - - const items = [ - ...(this.props.status === JOB_STATUS.ACTIVE - ? [ - { - label: ( - <> - - Change Password - - ), - items: [ - { - label: <>Translate, - onClick: () => { - this.props.changePasswordFn() - }, + const items = [ + ...(status === JOB_STATUS.ACTIVE + ? [ + { + id: JOB_MENU_ITEM_ID.CHANGE_PASSWORD, + label: ( + <> + + Change Password + + ), + items: [ + { + label: <>Translate, + onClick: () => { + changePasswordFn() }, - { - label: <>Revise, - onClick: () => { - this.props.changePasswordFn(1) - }, + }, + { + label: <>Revise, + onClick: () => { + changePasswordFn(1) }, - ...(this.props.job.has('revise_passwords') && - this.props.job.get('revise_passwords').size > 1 - ? [ - { - label: <>Revise 2, - onClick: () => { - this.props.changePasswordFn(2) - }, + }, + ...(job.has('revise_passwords') && + job.get('revise_passwords').size > 1 + ? [ + { + label: <>Revise 2, + onClick: () => { + changePasswordFn(2) }, - ] - : []), - ], + }, + ] + : []), + ], + }, + ] + : []), + ...(!isChunkOutsourced && config.splitEnabled && !isChunk + ? [ + { + id: JOB_MENU_ITEM_ID.SPLIT, + label: ( + <> + + Split + + ), + onClick: () => { + openSplitModalFn() }, - ] - : []), - ...(!this.props.isChunkOutsourced && - config.splitEnabled && - !this.props.isChunk + }, + ] + : !isChunkOutsourced && config.splitEnabled && isChunk ? [ { + id: JOB_MENU_ITEM_ID.MERGE, label: ( <> - - Split + + Merge ), onClick: () => { - this.props.openSplitModalFn() + openMergeModalFn() }, }, ] - : !this.props.isChunkOutsourced && - config.splitEnabled && - this.props.isChunk - ? [ - { - label: ( - <> - - Merge - - ), - onClick: () => { - this.props.openMergeModalFn() - }, - }, - ] - : []), - 'separator', - { - label: ( - <> - - Revise - - ), - onClick: () => { - window.open(this.props.reviseUrl, '_blank') - }, + : []), + 'separator', + { + id: JOB_MENU_ITEM_ID.REVISE, + label: ( + <> + + Revise + + ), + onClick: () => { + window.open(reviseUrl, '_blank') }, - ...this.getSecondPassReviewMenuLink(), - { - label: ( - <> - Quality report - - ), - onClick: () => { - window.open(qaReportUrl, '_blank') - }, + }, + ...getSecondPassReviewMenuLink(), + { + id: JOB_MENU_ITEM_ID.QA_REPORT, + label: ( + <> + Quality report + + ), + onClick: () => { + window.open(qAReportUrl, '_blank') }, - 'separator', - ...(this.props.getDownloadLabel - ? [ - { - label: this.props.getDownloadLabel.label, - onClick: () => { - this.props.getDownloadLabel.action() - }, - disabled: this.props.disableDownload, + }, + 'separator', + ...(downloadLabel + ? [ + { + id: JOB_MENU_ITEM_ID.DOWNLOAD, + label: downloadLabel.label, + onClick: () => { + downloadLabel.action() }, - ] - : []), - { - label: ( - <> - Original - - ), - onClick: () => { - window.open(originalUrl, '_blank') - }, + disabled: disableDownload, + }, + ] + : []), + { + id: JOB_MENU_ITEM_ID.ORIGINAL, + label: ( + <> + Original + + ), + onClick: () => { + window.open(originalUrl, '_blank') }, - { - label: ( - <> - Export XLIFF - - ), - onClick: () => { - window.open(exportXliffUrl, '_blank') - }, + }, + { + id: JOB_MENU_ITEM_ID.EXPORT_XLIFF, + label: ( + <> + Export XLIFF + + ), + onClick: () => { + window.open(exportXliffUrl, '_blank') }, - { - label: ( - <> - Export job TMX - - ), - onClick: () => { - window.open(jobTMXUrl, '_blank') - }, + }, + { + id: JOB_MENU_ITEM_ID.EXPORT_TMX, + label: ( + <> + Export job TMX + + ), + onClick: () => { + window.open(jobTMXUrl, '_blank') }, - 'separator', - ...(this.props.status === JOB_STATUS.ACTIVE - ? [ - { - label: ( - <> - - Archive job - - ), - onClick: () => { - this.props.archiveJobFn() - }, + }, + 'separator', + ...(status === JOB_STATUS.ACTIVE + ? [ + { + id: JOB_MENU_ITEM_ID.ARCHIVE, + label: ( + <> + + Archive job + + ), + onClick: () => { + archiveJobFn() }, - { - label: ( - <> - - Cancel job - - ), - onClick: () => { - this.props.cancelJobFn() - }, + }, + { + id: JOB_MENU_ITEM_ID.CANCEL, + label: ( + <> + + Cancel job + + ), + onClick: () => { + cancelJobFn() }, - ] - : []), - ...(this.props.status === JOB_STATUS.ARCHIVED - ? [ - { - label: ( - <> - - Unarchive job - - ), - onClick: () => { - this.props.activateJobFn() - }, + }, + ] + : []), + ...(status === JOB_STATUS.ARCHIVED + ? [ + { + id: JOB_MENU_ITEM_ID.UNARCHIVE, + label: ( + <> + + Unarchive job + + ), + onClick: () => { + activateJobFn() }, - { - label: ( - <> - - Cancel job - - ), - onClick: () => { - this.props.cancelJobFn() - }, + }, + { + id: JOB_MENU_ITEM_ID.CANCEL, + label: ( + <> + + Cancel job + + ), + onClick: () => { + cancelJobFn() }, - ] - : []), - ...(this.props.status === JOB_STATUS.CANCELLED - ? [ - { - label: ( - <> - - Resume job - - ), - onClick: () => { - this.props.activateJobFn() - }, + }, + ] + : []), + ...(status === JOB_STATUS.CANCELLED + ? [ + { + id: JOB_MENU_ITEM_ID.RESUME, + label: ( + <> + + Resume job + + ), + onClick: () => { + activateJobFn() }, - { - label: ( - <> - - Delete job permanently - - ), - onClick: () => { - this.props.deleteJobFn() - }, + }, + { + id: JOB_MENU_ITEM_ID.DELETE, + label: ( + <> + + Delete job permanently + + ), + onClick: () => { + deleteJobFn() }, - ] - : []), - ] - return ( - , - testId: 'job-menu-button', - }} - align={DROPDOWN_MENU_ALIGN.RIGHT} - /> + }, + ] + : []), + ] + .filter(({id}) => + typeof id === 'string' + ? !isJobChunks + ? isChunk + ? CHUNK_MENU_ITEM_ID.some((value) => value === id) + : true + : isJobChunks && isChunk + ? JOB_CHUNKS_MENU_ITEM_ID.some((value) => value === id) + : true + : true, ) - } + .reduce((acc, item) => { + if (item === 'separator' && acc[acc.length - 1] === 'separator') { + return acc + } + return [...acc, item] + }, []) + .filter((item, index, arr) => { + if (item !== 'separator') return true + return arr.slice(index + 1).some((i) => i !== 'separator') + }) + + return ( + , + testId: 'job-menu-button', + size: BUTTON_SIZE.ICON_SMALL, + }} + align={DROPDOWN_MENU_ALIGN.RIGHT} + /> + ) +} + +JobMenu.propTypes = { + job: PropTypes.object.isRequired, + project: PropTypes.object.isRequired, + jobId: PropTypes.number.isRequired, + status: PropTypes.string.isRequired, + qAReportUrl: PropTypes.string, + jobTMXUrl: PropTypes.string.isRequired, + exportXliffUrl: PropTypes.string.isRequired, + originalUrl: PropTypes.string.isRequired, + reviseUrl: PropTypes.string, + isChunkOutsourced: PropTypes.bool.isRequired, + isChunk: PropTypes.bool.isRequired, + isJobChunks: PropTypes.bool, + changePasswordFn: PropTypes.func, + openSplitModalFn: PropTypes.func, + openMergeModalFn: PropTypes.func.isRequired, + downloadLabel: PropTypes.object, + disableDownload: PropTypes.bool.isRequired, + archiveJobFn: PropTypes.func.isRequired, + cancelJobFn: PropTypes.func.isRequired, + activateJobFn: PropTypes.func.isRequired, + deleteJobFn: PropTypes.func.isRequired, } export default JobMenu diff --git a/public/js/components/projects/JobMenu.test.js b/public/js/components/projects/JobMenu.test.js index 8e42247514..8490e86fc0 100644 --- a/public/js/components/projects/JobMenu.test.js +++ b/public/js/components/projects/JobMenu.test.js @@ -30,6 +30,7 @@ const fakeProjectsData = { editingLogUrl: '/editlog/90-Y2Q3OTNjE5ZG629', qAReportUrl: '/revise-summary/90-Y2Q3OTNjE5ZG629', reviseUrl: '/revise/test/en-US-la-XN/90-0-a192d66ec1f5#58', + downloadLabel: {label: 'Draft'}, }, }, jobSplitted: { @@ -244,7 +245,7 @@ test('Check items href link', async () => { test('Splitted job: check Merge item', async () => { const {props} = getFakeProperties(fakeProjectsData.jobSplitted) - render() + render() await userEvent.click(screen.getByTestId('job-menu-button')) expect(screen.getByText('Merge')).toBeInTheDocument() diff --git a/public/js/components/projects/ProjectContainer.js b/public/js/components/projects/ProjectContainer.js index 8dfd4d0a0d..d02f069bb9 100644 --- a/public/js/components/projects/ProjectContainer.js +++ b/public/js/components/projects/ProjectContainer.js @@ -1,3 +1,4 @@ +import PropTypes from 'prop-types' import React, { useCallback, useContext, @@ -5,22 +6,11 @@ import React, { useRef, useState, } from 'react' -import moment from 'moment' -import {isUndefined} from 'lodash' - -import ManageConstants from '../../constants/ManageConstants' -import JobContainer from './JobContainer' -import UserActions from '../../actions/UserActions' +import {ProjectsBulkActionsContext} from './ProjectsBulkActions/ProjectsBulkActionsContext' +import {Checkbox, CHECKBOX_STATE} from '../common/Checkbox' +import {Controller, useForm} from 'react-hook-form' import ManageActions from '../../actions/ManageActions' -import ProjectsStore from '../../stores/ProjectsStore' -import {getLastProjectActivityLogAction} from '../../api/getLastProjectActivityLogAction' -import ModalsActions from '../../actions/ModalsActions' -import ConfirmMessageModal from '../modals/ConfirmMessageModal' -import UserStore from '../../stores/UserStore' -import { - DROPDOWN_MENU_ALIGN, - DropdownMenu, -} from '../common/DropdownMenu/DropdownMenu' +import {Input} from '../common/Input/Input' import { Button, BUTTON_HTML_TYPE, @@ -28,22 +18,33 @@ import { BUTTON_SIZE, BUTTON_TYPE, } from '../common/Button/Button' -import DotsHorizontal from '../../../img/icons/DotsHorizontal' -import {UserProjectDropdown} from './UserProjectDropdown' -import {Controller, useForm} from 'react-hook-form' -import {Input} from '../common/Input/Input' import IconEdit from '../icons/IconEdit' import Checkmark from '../../../img/icons/Checkmark' import IconClose from '../icons/IconClose' -import {ProjectsBulkActionsContext} from './ProjectsBulkActions/ProjectsBulkActionsContext' -import {Checkbox, CHECKBOX_STATE} from '../common/Checkbox' +import {JobContainer} from './JobContainer' +import {getLastProjectActivityLogAction} from '../../api/getLastProjectActivityLogAction' +import {isUndefined} from 'lodash' +import { + DROPDOWN_MENU_ALIGN, + DropdownMenu, +} from '../common/DropdownMenu/DropdownMenu' +import UserActions from '../../actions/UserActions' +import {UserProjectDropdown} from './UserProjectDropdown' import FileLog from '../../../img/icons/FileLog' import Archive from '../../../img/icons/Archive' -import Refresh from '../../../img/icons/Refresh' import Trash from '../../../img/icons/Trash' import FlipBackward from '../icons/FlipBackward' +import DotsHorizontal from '../../../img/icons/DotsHorizontal' +import ModalsActions from '../../actions/ModalsActions' +import ConfirmMessageModal from '../modals/ConfirmMessageModal' +import IconDown from '../icons/IconDown' +import ManageConstants from '../../constants/ManageConstants' +import UserStore from '../../stores/UserStore' +import ProjectsStore from '../../stores/ProjectsStore' +import {ChunksJobContainer} from './ChunksJobContainer' +import {fromJS} from 'immutable' -const ProjectContainer = ({ +export const ProjectContainer = ({ project, teams, team, @@ -55,15 +56,14 @@ const ProjectContainer = ({ ProjectsBulkActionsContext, ) + const {handleSubmit, control, reset} = useForm() + const idTeamProject = project.get('id_team') + const [isEditingName, setIsEditingName] = useState(false) const [lastAction, setLastAction] = useState() const [jobsActions, setJobsActions] = useState() const [idTeamSelected, setIdTeamSelected] = useState(idTeamProject) - const [shouldShowMoreActions, setShouldShowMoreActions] = useState(false) - const [isEditingName, setIsEditingName] = useState(false) - - const {handleSubmit, control, reset} = useForm() const projectRef = useRef() const projectTeam = useRef() @@ -94,10 +94,128 @@ const ProjectContainer = ({ [project, selectedUser, team], ) + useEffect(() => { + getLastAction.current() + + const hideProject = (projectCompare) => { + if (project.get('id') === projectCompare.get('id')) { + projectRef.current.style.transition = 'transform 0.5s ease-in-out' + projectRef.current.style.transform = 'translateX(-2000px)' + } + } + + ProjectsStore.addListener(ManageConstants.HIDE_PROJECT, hideProject) + ProjectsStore.addListener( + ManageConstants.CHANGE_PROJECT_ASSIGNEE, + hideProjectAfterChangeAssignee, + ) + + return () => { + ProjectsStore.removeListener(ManageConstants.HIDE_PROJECT, hideProject) + ProjectsStore.removeListener( + ManageConstants.CHANGE_PROJECT_ASSIGNEE, + hideProjectAfterChangeAssignee, + ) + } + }, [project, hideProjectAfterChangeAssignee]) + useEffect(() => { setIdTeamSelected(idTeamProject) }, [idTeamProject]) + const changeNameFormId = `project-change-name-${project.get('id')}` + + const jobsBulkForCurrentProject = project + .get('jobs') + .toJS() + .filter(({id}) => jobsBulk.some((value) => value === id)) + + const handleFormSubmit = (formData) => { + const {name} = formData + ManageActions.changeProjectName(project, name) + setIsEditingName(false) + } + + const changeNameForm = ( +
    { + reset() + setIsEditingName(false) + }} + > +
    + ( + + )} + /> +
    +
    + ) + + const projectNameElements = ( +
    + {isEditingName ? ( + <> + {changeNameForm} + {isEditingName && ( + <> + + + + + )} + + ) : ( + <> +
    + {project.get('name')} +
    + + + )} +
    + ) + + const getActivityLogUrl = () => { + return '/activityLog/' + project.get('id') + '/' + project.get('password') + } + const thereIsChunkOutsourced = (idJob) => { const outsourceChunk = project.get('jobs').find(function (item) { return !!item.get('outsource') && item.get('id') === idJob @@ -105,33 +223,137 @@ const ProjectContainer = ({ return !isUndefined(outsourceChunk) } - const removeProject = () => { - ManageActions.updateStatusProject(project, 'cancel') + const getLastAction = useRef() + getLastAction.current = () => { + getLastProjectActivityLogAction({ + id: project.get('id'), + password: project.get('password'), + }).then((data) => { + const lastAction = data.activity[0] ? data.activity[0] : null + setLastAction(lastAction) + setJobsActions(data.activity) + }) } - const archiveProject = () => { - ManageActions.updateStatusProject(project, 'archive') + const getLastJobAction = (idJob) => { + //Last Activity Log Action + let lastAction + if (jobsActions && jobsActions.length > 0) { + lastAction = jobsActions.find(function (job) { + return job.id_job == idJob + }) + } + return lastAction } - const activateProject = () => { - ManageActions.updateStatusProject(project, 'active') + const getJobContainer = () => { + const jobs = project.get('jobs') + + const chunks = jobs.toJS().reduce((acc, job) => { + const id = job.id + if ( + acc.some((jobItem) => + Array.isArray(jobItem) + ? jobItem.some((chunkItem) => chunkItem.id === id) + : jobItem.id === id, + ) + ) { + const index = acc.findIndex((jobItem) => + Array.isArray(jobItem) + ? jobItem.some((chunkItem) => chunkItem.id === id) + : jobItem.id === id, + ) + if (Array.isArray(acc[index])) { + acc[index].push(job) + } else { + acc[index] = [acc[index], job] + } + + return acc + } + + return [...acc, job] + }, []) + + return chunks.map((item) => { + const job = fromJS(Array.isArray(item) ? item[0] : item) + + const lastAction = getLastJobAction(job.get('id')) + const isChunkOutsourced = thereIsChunkOutsourced(job.get('id')) + + if (Array.isArray(item)) { + return ( + fromJS(itemJS))} + project={project} + changeStatusFn={changeStatusFn} + downloadTranslationFn={downloadTranslationFn} + isChunk={true} + lastAction={lastAction} + isChunkOutsourced={isChunkOutsourced} + activityLogUrl={getActivityLogUrl()} + isChecked={jobsBulk.some((jobId) => jobId === job.get('id'))} + onCheckedJob={onCheckedJob} + /> + ) + } + + return ( + jobId === job.get('id'))} + onCheckedJob={onCheckedJob} + /> + ) + }) } - const deleteProject = () => { - const props = { - text: - 'You are about to delete this project permanently. This action cannot be undone.' + - ' Are you sure you want to proceed?', - successText: 'Yes, delete it', - successCallback: () => { - ManageActions.updateStatusProject(project, 'delete') - }, - cancelCallback: () => {}, + const changeTeam = (value) => { + if (project.get('id_team') !== parseInt(value)) { + ManageActions.changeProjectTeam(value, project) + projectTeam.current = teams.find( + (team) => parseInt(team.get('id')) === parseInt(value), + ) } - ModalsActions.showModalComponent( - ConfirmMessageModal, - props, - 'Confirmation required', + } + + const getDropDownTeams = () => { + const teamsCollections = teams?.toJS() ?? [] + const items = teamsCollections.map((team) => ({ + label: team.name, + selected: team.id === idTeamSelected, + onClick: () => { + changeTeam(team.id) + setIdTeamSelected(team.id) + }, + })) + + return ( + + {teamsCollections.find(({id}) => id === idTeamSelected)?.name} + + + ), + testId: 'teams-dropdown', + }} + items={items} + /> ) } @@ -159,13 +381,64 @@ const ProjectContainer = ({ } } - const changeTeam = (value) => { - if (project.get('id_team') !== parseInt(value)) { - ManageActions.changeProjectTeam(value, project) - projectTeam.current = teams.find( - (team) => parseInt(team.get('id')) === parseInt(value), - ) + const openAddMember = () => + ManageActions.openAddTeamMemberModal(projectTeam.current.toJS()) + + const createUserDropDown = (users) => { + return ( + + ) + } + + const getDropDownUsers = () => { + let result = '' + if (team.get('type') == 'personal') { + if (teams) { + if (projectTeam.current && projectTeam.current.get('members')) { + result = createUserDropDown(projectTeam.current.get('members')) + } else { + UserActions.getAllTeams() + } + } + } else if (team.get('members')) { + result = createUserDropDown(team.get('members')) } + return result + } + + const removeProject = () => + ManageActions.updateStatusProject(project, 'cancel') + + const archiveProject = () => + ManageActions.updateStatusProject(project, 'archive') + + const activateProject = () => + ManageActions.updateStatusProject(project, 'active') + + const deleteProject = () => { + const props = { + text: + 'You are about to delete this project permanently. This action cannot be undone.' + + ' Are you sure you want to proceed?', + successText: 'Yes, delete it', + successCallback: () => { + ManageActions.updateStatusProject(project, 'delete') + }, + cancelCallback: () => {}, + } + ModalsActions.showModalComponent( + ConfirmMessageModal, + props, + 'Confirmation required', + ) } const getDropdownProjectMenu = (activityLogUrl) => { @@ -254,7 +527,8 @@ const ProjectContainer = ({ , + size: BUTTON_SIZE.ICON_SMALL, + children: , testId: 'project-menu-dropdown', }} align={DROPDOWN_MENU_ALIGN.RIGHT} @@ -263,432 +537,67 @@ const ProjectContainer = ({ ) } - const getLastAction = useRef() - getLastAction.current = () => { - getLastProjectActivityLogAction({ - id: project.get('id'), - password: project.get('password'), - }).then((data) => { - const lastAction = data.activity[0] ? data.activity[0] : null - setLastAction(lastAction) - setJobsActions(data.activity) - }) - } - - const getLastJobAction = (idJob) => { - //Last Activity Log Action - let lastAction - if (jobsActions && jobsActions.length > 0) { - lastAction = jobsActions.find(function (job) { - return job.id_job == idJob - }) - } - return lastAction - } - - const getActivityLogUrl = () => { - return '/activityLog/' + project.get('id') + '/' + project.get('password') - } - - const getLastActionDate = () => { - let date = new Date(lastAction.event_date) + const getFormattedDate = (dateString) => { + const date = new Date(dateString) return date.toDateString() } - const jobsBulkForCurrentProject = project - .get('jobs') - .toJS() - .filter(({id}) => jobsBulk.some((value) => value === id)) - - const getJobsList = (jobsLength) => { - const jobsList = [] - let chunks = [], - index - const tempIdsArray = [] - let orderedJobs = project.get('jobs') - orderedJobs.map(function (job, i) { - let next_job_id = orderedJobs.get(i + 1) - ? orderedJobs.get(i + 1).get('id') - : 0 - //To check if is a chunk (jobs with same id) - let isChunk = false - if (tempIdsArray.indexOf(job.get('id')) > -1) { - isChunk = true - index++ - } else if ( - orderedJobs.get(i + 1) && - orderedJobs.get(i + 1).get('id') === job.get('id') - ) { - //The first of the Chunk - isChunk = true - tempIdsArray.push(job.get('id')) - index = 1 - } else { - index = 0 - } - - const lastAction = getLastJobAction(job.get('id')) - const isChunkOutsourced = thereIsChunkOutsourced(job.get('id')) - - let item = ( - jobId === job.get('id'))} - onCheckedJob={onCheckedJob} - isCheckboxVisible={ - shouldShowMoreActions || jobsBulkForCurrentProject.length - } - /> - ) - chunks.push(item) - if (job.get('id') !== next_job_id) { - let jobList = ( -
    -
    -
    {chunks}
    -
    -
    - ) - jobsList.push(jobList) - chunks = [] - } - }) - - return jobsList - } - - const openAddMember = () => { - ManageActions.openAddTeamMemberModal(projectTeam.current.toJS()) - } - - const createUserDropDown = (users) => { - return ( - - ) - } - - /** - * To add informations from the plugins - * @returns {string} - */ - const moreProjectInfo = () => { - return '' - } - - const getDropDownUsers = () => { - let result = '' - if (team.get('type') == 'personal') { - if (teams) { - if (projectTeam.current && projectTeam.current.get('members')) { - result = createUserDropDown(projectTeam.current.get('members')) - } else { - UserActions.getAllTeams() - } - } - } else if (team.get('members')) { - result = createUserDropDown(team.get('members')) - } - return result - } - - const getDropDownTeams = () => { - const teamsCollections = teams?.toJS() ?? [] - const items = teamsCollections.map((team) => ({ - label: team.name, - selected: team.id === idTeamSelected, - onClick: () => { - changeTeam(team.id) - setIdTeamSelected(team.id) - }, - })) - - return ( - id === idTeamSelected) - ?.name, - testId: 'teams-dropdown', - }} - items={items} - /> - ) - } - - const getDueDate = () => { - if (project.get('due_date')) { - return ( -
    -
    - {'Due Date: ' + moment(project.get('due_date')).format('LLLL')} -
    -
    - ) - } - return ( -
    - ) - } - - useEffect(() => { - getLastAction.current() - - const hideProject = (projectCompare) => { - if (project.get('id') === projectCompare.get('id')) { - projectRef.current.style.transition = 'transform 0.5s ease-in-out' - projectRef.current.style.transform = 'translateX(-2000px)' - } - } - - ProjectsStore.addListener(ManageConstants.HIDE_PROJECT, hideProject) - ProjectsStore.addListener( - ManageConstants.CHANGE_PROJECT_ASSIGNEE, - hideProjectAfterChangeAssignee, - ) - - return () => { - ProjectsStore.removeListener(ManageConstants.HIDE_PROJECT, hideProject) - ProjectsStore.removeListener( - ManageConstants.CHANGE_PROJECT_ASSIGNEE, - hideProjectAfterChangeAssignee, - ) - } - }, [project, hideProjectAfterChangeAssignee]) - - const handleFormSubmit = (formData) => { - const {name} = formData - ManageActions.changeProjectName(project, name) - setIsEditingName(false) - } - - const changeNameFormId = `project-change-name-${project.get('id')}` - - const changeNameForm = ( -
    { - reset() - setIsEditingName(false) - }} - > -
    - ( - - )} - /> -
    -
    - ) - - const activityLogUrl = getActivityLogUrl() - const dropdownProjectMenu = getDropdownProjectMenu(activityLogUrl) - const jobsLength = project.get('jobs').size - - //The list of jobs - const jobsList = getJobsList(jobsLength) - - // Users dropdown - const dropDownUsers = getDropDownUsers() - const dropDownTeams = getDropDownTeams() - - const state = project.get('is_archived') ? ( -
    (archived)
    - ) : project.get('is_cancelled') ? ( -
    (cancelled)
    - ) : ( - '' - ) - return ( -
    -
    setShouldShowMoreActions(true)} - onMouseLeave={() => setShouldShowMoreActions(false)} - > -
    -
    -
    -
    -
    - onCheckedProject(project.get('id'))} - value={ - jobsBulkForCurrentProject.length === 0 - ? CHECKBOX_STATE.UNCHECKED - : jobsBulkForCurrentProject.length === - project.get('jobs').size - ? CHECKBOX_STATE.CHECKED - : CHECKBOX_STATE.INDETERMINATE - } - /> -
    - {'(' + project.get('id') + ')'} -
    - {isEditingName ? ( - changeNameForm - ) : ( -
    - {project.get('name')} -
    - )} -
    - {shouldShowMoreActions && !isEditingName && ( - - )} - {isEditingName && ( - <> - - - - - )} - {(state !== '' || project.get('is_cancelled')) && ( -
    {state}
    - )} - {moreProjectInfo()} -
    -
    -
    - -
    -
    -
    -
    - {dropDownTeams} - {dropDownUsers} - {dropdownProjectMenu} -
    -
    -
    +
    +
    +
    + onCheckedProject(project.get('id'))} + value={ + jobsBulkForCurrentProject.length === 0 + ? CHECKBOX_STATE.UNCHECKED + : jobsBulkForCurrentProject.length === project.get('jobs').size + ? CHECKBOX_STATE.CHECKED + : CHECKBOX_STATE.INDETERMINATE + } + /> +
    + {projectNameElements} + + ID: {project.get('id')} +
    -
    -
    - {jobsList} -
    -
    - -
    - {getDueDate()} - {lastAction ? ( - - ) : ( - - )} +
    + {getDropDownTeams()} + {getDropDownUsers()} + {getDropdownProjectMenu(getActivityLogUrl())}
    + {getJobContainer()} +
    + {lastAction && ( + + )} + Created: {getFormattedDate(project.get('create_date'))} +
    ) } -export default ProjectContainer +ProjectContainer.propTypes = { + project: PropTypes.object, + teams: PropTypes.object, + team: PropTypes.object, + selectedUser: PropTypes.string, + changeStatusFn: PropTypes.func, + downloadTranslationFn: PropTypes.func, +} diff --git a/public/js/components/projects/ProjectContainer.test.js b/public/js/components/projects/ProjectContainer.test.js index 2fedabfc3a..9ae22ca993 100644 --- a/public/js/components/projects/ProjectContainer.test.js +++ b/public/js/components/projects/ProjectContainer.test.js @@ -1,7 +1,7 @@ -import {render, screen} from '@testing-library/react' +import {act, render, screen} from '@testing-library/react' import React from 'react' import {createRoot} from 'react-dom/client' -import ProjectContainer from './ProjectContainer' +import {ProjectContainer} from './ProjectContainer' import {fromJS} from 'immutable' import {http, HttpResponse} from 'msw' @@ -16,7 +16,7 @@ const modalElement = document.createElement('div') modalElement.id = 'modal' document.body.appendChild(modalElement) const mountPoint = createRoot(modalElement) -afterAll(() => mountPoint.unmount()) +afterAll(() => act(() => mountPoint.unmount())) global.config = { enable_outsource: 1, @@ -411,12 +411,6 @@ const executeMswServer = () => { ) } -const getActivityLogUrl = (projectId, password) => - `/activityLog/${projectId}/${password}` -const createActivityLogUrl = (project) => { - return getActivityLogUrl(project.get('id'), project.get('password')) -} - class ResizeObserver { observe() {} unobserve() {} @@ -445,7 +439,7 @@ test('Rendering elements', async () => { , ) - expect(screen.getByText(`(${project.get('id')})`)).toBeInTheDocument() + expect(screen.getByTestId('project-id')).toBeInTheDocument() const projectName = screen.getByTestId('project-name').textContent expect(projectName).toBe(project.get('name')) await userEvent.click(screen.getByTestId('project-teams')) @@ -459,8 +453,8 @@ test('Rendering elements', async () => { expect(screen.getByText(`by ${first_name}`)).toBeInTheDocument() - const href = screen.getByTestId('last-action-activity').getAttribute('href') - expect(href).toBe(createActivityLogUrl(project)) + expect(screen.getByTestId('last-action-activity')).toBeInTheDocument() + const dropdown = screen.getByTestId('teams-dropdown') expect(dropdown).toBeInTheDocument() diff --git a/public/js/components/projects/ProjectsBulkActions/ProjectsBulkActions.js b/public/js/components/projects/ProjectsBulkActions/ProjectsBulkActions.js index 8879887aab..16b49cacf9 100644 --- a/public/js/components/projects/ProjectsBulkActions/ProjectsBulkActions.js +++ b/public/js/components/projects/ProjectsBulkActions/ProjectsBulkActions.js @@ -211,27 +211,32 @@ export const ProjectsBulkActions = ({ (projectId) => { const currentProject = projects.find(({id}) => id === projectId) + const currentProjectJobs = currentProject.jobs.reduce( + (acc, cur) => (acc.some(({id}) => id === cur.id) ? acc : [...acc, cur]), + [], + ) + if (shiftKeyRef.current.isPressed) { const lastJobIdProject = - currentProject.jobs[currentProject.jobs.length - 1].id + currentProjectJobs[currentProject.jobs.length - 1].id onCheckedJob( shiftKeyRef.current.startJob.id > lastJobIdProject ? lastJobIdProject - : currentProject.jobs[0].id, + : currentProjectJobs[0].id, ) } else { setJobsBulk((prevState) => { - const jobsBulkForCurrentProject = currentProject.jobs.filter(({id}) => + const jobsBulkForCurrentProject = currentProjectJobs.filter(({id}) => prevState.some((value) => value === id), ) const isCheckedAllJobs = - jobsBulkForCurrentProject.length === currentProject.jobs.length + jobsBulkForCurrentProject.length === currentProjectJobs.length if ( !isCheckedAllJobs && - prevState.length + currentProject.jobs.length > MAX_JOBS_SELECTABLE + prevState.length + currentProjectJobs.length > MAX_JOBS_SELECTABLE ) return prevState @@ -245,12 +250,12 @@ export const ProjectsBulkActions = ({ (value) => !jobsBulkForCurrentProject.some(({id}) => id === value), ), - ...currentProject.jobs.map(({id}) => id), + ...currentProjectJobs.map(({id}) => id), ] }) } - shiftKeyRef.current.startJob = currentProject.jobs[0] + shiftKeyRef.current.startJob = currentProjectJobs[0] }, [projects, onCheckedJob], ) diff --git a/public/js/components/projects/ProjectsContainer.js b/public/js/components/projects/ProjectsContainer.js index bebb33b58f..d3fbf5ce2e 100644 --- a/public/js/components/projects/ProjectsContainer.js +++ b/public/js/components/projects/ProjectsContainer.js @@ -1,323 +1,244 @@ -import React from 'react' -import $ from 'jquery' -import {flushSync} from 'react-dom' -import ProjectContainer from './ProjectContainer' -import UserConstants from '../../constants/UserConstants' -import ManageConstants from '../../constants/ManageConstants' +import PropTypes from 'prop-types' +import React, {useEffect, useState} from 'react' import ProjectsStore from '../../stores/ProjectsStore' +import ManageConstants from '../../constants/ManageConstants' +import {ProjectsBulkActions} from './ProjectsBulkActions' +import {ProjectContainer} from './ProjectContainer' +import UserConstants from '../../constants/UserConstants' import UserStore from '../../stores/UserStore' +import {DASHBOARD_REQUEST_PROJECTS_STATUS} from '../../constants/Constants' +import {SPINNER_LOADER_SIZE, SpinnerLoader} from '../common/SpinnerLoader' +import {Button, BUTTON_TYPE, BUTTON_SIZE} from '../common/Button/Button' import ManageActions from '../../actions/ManageActions' -import {fromJS} from 'immutable' -import {ProjectsBulkActions} from './ProjectsBulkActions' - -class ProjectsContainer extends React.Component { - constructor(props) { - super(props) - this.state = { - projects: fromJS([]), - more_projects: false, - reloading_projects: false, - team: this.props.team, - teams: this.props.teams, - filtering: false, +import CatToolActions from '../../actions/CatToolActions' + +export const ProjectsContainer = ({ + team, + teams, + downloadTranslationFn, + selectedUser, + requestProjectsStatus, +}) => { + const [projects, setProjects] = useState() + const [teamState, setTeamState] = useState(team) + const [teamsState, setTeamsState] = useState(teams) + const [isFilterApplied, setIsFilterApplied] = useState(false) + const [reachNoMoreProjects, setReachNoMoreProjects] = useState(false) + + useEffect(() => { + const renderProjects = (projects, team, teams, hideSpinner, filtering) => { + setProjects(projects) + setTeamState((prevState) => (team ? team : prevState)) + setTeamsState((prevState) => (teams ? teams : prevState)) + setIsFilterApplied(filtering) + setReachNoMoreProjects((prevState) => (hideSpinner ? prevState : false)) } - this.renderProjects = this.renderProjects.bind(this) - this.updateProjects = this.updateProjects.bind(this) - this.updateTeam = this.updateTeam.bind(this) - this.updateTeams = this.updateTeams.bind(this) - this.hideSpinner = this.hideSpinner.bind(this) - this.showProjectsReloadSpinner = this.showProjectsReloadSpinner.bind(this) - } - - renderProjects(projects, team, teams, hideSpinner, filtering) { - let more_projects = true - if (hideSpinner) { - more_projects = this.state.more_projects - } - let teamState = team ? team : this.state.team - let teamsState = teams ? teams : this.state.teams - let filteringState = filtering ? filtering : this.state.filtering - this.setState({ - projects: projects, - more_projects: more_projects, - reloading_projects: false, - team: teamState, - teams: teamsState, - filtering: filteringState, + const updateProjects = (projects) => setProjects(projects) + const updateTeams = (teams) => setTeamsState(teams) + const updateTeam = (team) => + setTeamState((prevState) => + team.get('id') === prevState.get('id') ? team : prevState, + ) + const noMoreProjects = () => setReachNoMoreProjects(true) + + ProjectsStore.addListener(ManageConstants.RENDER_PROJECTS, renderProjects) + ProjectsStore.addListener(ManageConstants.UPDATE_PROJECTS, updateProjects) + UserStore.addListener(UserConstants.UPDATE_TEAM, updateTeam) + UserStore.addListener(UserConstants.UPDATE_TEAMS, updateTeams) + UserStore.addListener(UserConstants.RENDER_TEAMS, updateTeams) + ProjectsStore.addListener(ManageConstants.NO_MORE_PROJECTS, noMoreProjects) + + setTimeout(() => { + const notification = { + title: 'Notification', + text: 'Lorem ipsum bla bla', + type: 'success', + autoDismiss: false, + } + CatToolActions.addNotification(notification) }) - } - updateTeam(team) { - if (team.get('id') === this.state.team.get('id')) { - this.setState({ - team: team, - }) + return () => { + ProjectsStore.removeListener( + ManageConstants.RENDER_PROJECTS, + renderProjects, + ) + ProjectsStore.removeListener( + ManageConstants.UPDATE_PROJECTS, + updateProjects, + ) + UserStore.removeListener(UserConstants.UPDATE_TEAM, updateTeam) + UserStore.removeListener(UserConstants.UPDATE_TEAMS, updateTeams) + UserStore.removeListener(UserConstants.RENDER_TEAMS, updateTeams) + ProjectsStore.removeListener( + ManageConstants.NO_MORE_PROJECTS, + noMoreProjects, + ) } - } - - updateTeams(teams) { - this.setState({ - teams: teams, - }) - } - - updateProjects(projects) { - flushSync(() => - this.setState({ - projects: projects, - }), - ) - } + }, []) - hideSpinner() { - this.setState({ - more_projects: false, - }) - } + const getEmptyState = () => { + const thereAreMembers = + (teamState.get('members') && teamState.get('members').size > 1) || + (teamState.get('pending_invitations') && + teamState.get('pending_invitations').size > 0) || + teamState.get('type') === 'personal' - showProjectsReloadSpinner() { - this.setState({ - reloading_projects: true, - }) - } + const isProjectsEmpty = + typeof projects !== 'undefined' && projects.size === 0 - openAddMember() { - ManageActions.openModifyTeamModal(this.state.team.toJS()) - } - - createNewProject() { - window.open(`/?idTeam=${this.state.team.get('id')}`, '_blank') - } - - getButtonsNoProjects() { - if (!this.state.team) return - - let thereAreMembers = - (this.state.team.get('members') && - this.state.team.get('members').size > 1) || - (this.state.team.get('pending_invitations') && - this.state.team.get('pending_invitations').size > 0) || - this.state.team.get('type') === 'personal' return (
    - {this.state.filtering ? ( + {isFilterApplied ? (
    No Projects Found
    - ) : this.state.team.get('type') === 'personal' ? ( + ) : isProjectsEmpty && teamState.get('type') === 'personal' ? ( ) : ( - + ) )}
    ) } - componentDidMount() { - ProjectsStore.addListener( - ManageConstants.RENDER_PROJECTS, - this.renderProjects, - ) - // ProjectsStore.addListener(ManageConstants.RENDER_ALL_TEAM_PROJECTS, this.renderAllTeamssProjects); - ProjectsStore.addListener( - ManageConstants.UPDATE_PROJECTS, - this.updateProjects, - ) - ProjectsStore.addListener( - ManageConstants.NO_MORE_PROJECTS, - this.hideSpinner, - ) - ProjectsStore.addListener( - ManageConstants.SHOW_RELOAD_SPINNER, - this.showProjectsReloadSpinner, - ) - UserStore.addListener(UserConstants.UPDATE_TEAM, this.updateTeam) - UserStore.addListener(UserConstants.UPDATE_TEAMS, this.updateTeams) - UserStore.addListener(UserConstants.RENDER_TEAMS, this.updateTeams) - } - - componentWillUnmount() { - ProjectsStore.removeListener( - ManageConstants.RENDER_PROJECTS, - this.renderProjects, - ) - // ProjectsStore.removeListener(ManageConstants.RENDER_ALL_TEAM_PROJECTS, this.renderAllTeamssProjects); - ProjectsStore.removeListener( - ManageConstants.UPDATE_PROJECTS, - this.updateProjects, - ) - ProjectsStore.removeListener( - ManageConstants.NO_MORE_PROJECTS, - this.hideSpinner, - ) - ProjectsStore.removeListener( - ManageConstants.SHOW_RELOAD_SPINNER, - this.showProjectsReloadSpinner, - ) - UserStore.removeListener(UserConstants.UPDATE_TEAM, this.updateTeam) - UserStore.removeListener(UserConstants.UPDATE_TEAMS, this.updateTeams) - UserStore.removeListener(UserConstants.RENDER_TEAMS, this.updateTeams) - } - - componentDidUpdate() { - let self = this - if (!this.state.more_projects) { - setTimeout(function () { - $(self.spinner).css('visibility', 'hidden') - }, 3000) - } - } - - shouldComponentUpdate(nextProps, nextState) { - return ( - !nextState.projects.equals(this.state.projects) || - nextState.more_projects !== this.state.more_projects || - nextState.reloading_projects !== this.state.reloading_projects || - !nextState.team.equals(this.state.team) || - !nextState.teams.equals(this.state.teams) - ) - } - - render() { - let projects = this.state.projects - - let items = projects.map((project) => ( - - )) - - let spinner = '' - if (this.state.more_projects && projects.size > 9) { - spinner = ( -
    -
    -
    -
    Loading more projects
    -
    + return ( +
    + {projects?.size > 0 && ( +
    +

    Projects

    +
    + Legend: + + + Unconfirmed + + + + Translated + + + + Revise + + + + Revise 2 +
    - ) - } else if (projects.size > 9) { - spinner = ( -
    (this.spinner = spinner)} - > -
    -
    No more projects
    + )} + + + {projects?.size > 0 ? ( +
    + {projects.map((project) => ( + + ))}
    -
    - ) - } - - if (!items.size) { - items = this.getButtonsNoProjects() - spinner = '' - } + ) : ( + getEmptyState() + )} + - var spinnerReloadProjects = '' - if (this.state.reloading_projects) { - var spinnerContainer = { - position: 'absolute', - height: '100%', - width: '100%', - backgroundColor: 'rgba(76, 69, 69, 0.3)', - top: $(window).scrollTop(), - left: 0, - zIndex: 3, - } - spinnerReloadProjects = ( -
    -
    -
    Updating Projects
    -
    + {reachNoMoreProjects ? ( +
    +
    No more projects
    - ) - } - - return ( -
    -
    - - {this.props.fetchingProjects ? ( -
    -
    Loading Projects
    -
    - ) : ( - - {spinnerReloadProjects} - {items} - {spinner} - - )} -
    + ) : ( +
    +
    -
    - ) - } + )} +
    + ) } -export default ProjectsContainer +ProjectsContainer.propTypes = { + team: PropTypes.object, + teams: PropTypes.object, + downloadTranslationFn: PropTypes.func, + selectedUser: PropTypes.string, + requestProjectsStatus: PropTypes.oneOf( + Object.values(DASHBOARD_REQUEST_PROJECTS_STATUS), + ), +} diff --git a/public/js/components/projects/ProjectsContainer.test.js b/public/js/components/projects/ProjectsContainer.test.js index 6074a09e2d..bf39bf98f7 100644 --- a/public/js/components/projects/ProjectsContainer.test.js +++ b/public/js/components/projects/ProjectsContainer.test.js @@ -3,7 +3,7 @@ import React from 'react' import {fromJS} from 'immutable' import {http, HttpResponse} from 'msw' -import ProjectsContainer from './ProjectsContainer' +import {ProjectsContainer} from './ProjectsContainer' import ManageActions from '../../actions/ManageActions' import {mswServer} from '../../../mocks/mswServer' import userMock from '../../../mocks/userMock' @@ -763,6 +763,10 @@ test('No projects found with team type personal', () => { render() + act(() => { + ManageActions.updateProjects([]) + }) + expect(screen.getByText('Create Project')).toBeInTheDocument() expect(screen.getByText('Welcome to your Personal area')).toBeInTheDocument() }) @@ -776,6 +780,10 @@ test('No projects found with team type general', () => { render() + act(() => { + ManageActions.updateProjects([]) + }) + expect(screen.getByText(`Welcome to ${team.get('name')}`)).toBeInTheDocument() expect(screen.getByText('Create Project')).toBeInTheDocument() expect(screen.getByText('Add member')).toBeInTheDocument() diff --git a/public/js/components/projects/UserProjectDropdown.js b/public/js/components/projects/UserProjectDropdown.js index 9b1e91e0ae..a6f348cac2 100644 --- a/public/js/components/projects/UserProjectDropdown.js +++ b/public/js/components/projects/UserProjectDropdown.js @@ -1,4 +1,4 @@ -import React, {useCallback, useContext, useRef, useState} from 'react' +import React, {useCallback, useContext, useState} from 'react' import PropTypes from 'prop-types' import {BUTTON_SIZE, BUTTON_TYPE, Button} from '../common/Button/Button' import IconAdd from '../icons/IconAdd' @@ -7,6 +7,7 @@ import {INPUT_SIZE, Input} from '../common/Input/Input' import IconSearch from '../icons/IconSearch' import {ApplicationWrapperContext} from '../common/ApplicationWrapper/ApplicationWrapperContext' import IconClose from '../icons/IconClose' +import * as Popover from '@radix-ui/react-popover' export const UserProjectDropdown = ({ users, @@ -17,11 +18,9 @@ export const UserProjectDropdown = ({ }) => { const {userInfo} = useContext(ApplicationWrapperContext) - const [isDropdownVisible, setIsDropdownVisible] = useState(false) + const [open, setOpen] = useState(false) const [filterUsers, setFilterUsers] = useState() - const wrapperRef = useRef() - const selectedUser = users.find(({user}) => user.uid === idAssignee) const isPersonalTeam = userInfo ? userInfo.teams.find(({id}) => id === project.id_team).type === 'personal' @@ -32,43 +31,9 @@ export const UserProjectDropdown = ({ [], ) - const closeDropdown = useCallback((e) => { - if (e) e.stopPropagation() - if (wrapperRef.current && !wrapperRef.current.contains(e?.target)) { - window.eventHandler.removeEventListener( - 'click.userprojectdropdown', - closeDropdown, - ) - - setIsDropdownVisible(false) - } - }, []) - - const toggleDropdown = () => { - if (isDropdownVisible) { - window.eventHandler.removeEventListener( - 'click.userprojectdropdown', - closeDropdown, - ) - } else { - window.eventHandler.addEventListener( - 'click.userprojectdropdown', - closeDropdown, - ) - } + const handlerAddMember = () => openAddMember() - setIsDropdownVisible((prevState) => !prevState) - } - - const handlerAddMember = () => { - setIsDropdownVisible(false) - openAddMember() - } - - const onChangeUser = (userData) => { - setIsDropdownVisible(false) - changeUser(userData.user.uid) - } + const onChangeUser = (userData) => changeUser(userData.user.uid) const getImgUser = (userData) => { const {user_metadata: metadata, user} = userData @@ -100,70 +65,75 @@ export const UserProjectDropdown = ({ const isNotAssignee = !selectedUser return ( -
    - -
    -
      -
    • - Add new member -
    • -
    • - } - /> -
    • - {usersList.length > 0 ? ( - usersList.map((userData) => ( -
    • onChangeUser(userData)} - > - {getImgUser(userData)} - {`${userData.user.first_name} ${userData.user.last_name}`} -
    • - )) + + +
    -
    -
    + + + + +
    +
      +
    • + Add new member +
    • +
    • + } + /> +
    • + {usersList.length > 0 ? ( + usersList.map((userData) => ( +
    • onChangeUser(userData)} + > + {getImgUser(userData)} + {`${userData.user.first_name} ${userData.user.last_name}`} +
    • + )) + ) : ( + No results found. + )} +
    +
    +
    +
    + ) } diff --git a/public/js/components/quality_report/FileDetails.js b/public/js/components/quality_report/FileDetails.js index d13649a580..95f12a6e3e 100644 --- a/public/js/components/quality_report/FileDetails.js +++ b/public/js/components/quality_report/FileDetails.js @@ -1,18 +1,21 @@ import React from 'react' import SegmentQR from './SegmentQR' +import FileIcon from '../../../img/icons/FileIcon' +import FileTypeFile from '../../../img/icons/FileTypeFile' +import CommonUtils from '../../utils/commonUtils' -class FileDetails extends React.Component { - getSegments() { +function FileDetails(props) { + const getSegments = () => { let segments = [] - this.props.segments.forEach((item) => { + props.segments.forEach((item) => { let segment = ( ) segments.push(segment) @@ -20,16 +23,18 @@ class FileDetails extends React.Component { return segments } - render() { - return ( -
    -
    - FILE {this.props.file.get('file_name')} -
    -
    {this.getSegments()}
    + return ( +
    +
    + {CommonUtils.getFileIcon( + props.file.get('file_name').split('.').slice(-1)[0], + 16, + )} + FILE {props.file.get('file_name')}
    - ) - } +
    {getSegments()}
    +
    + ) } export default FileDetails diff --git a/public/js/components/quality_report/FilterSegments.js b/public/js/components/quality_report/FilterSegments.js index 738fad740d..69f70f9d50 100644 --- a/public/js/components/quality_report/FilterSegments.js +++ b/public/js/components/quality_report/FilterSegments.js @@ -1,252 +1,243 @@ -import React from 'react' +/* global config */ +import React, {useState, useMemo, useCallback} from 'react' import InputField from '../common/InputField' import {Select} from '../common/Select' +import FilterIcon from '../../../img/icons/FilterIcon' -class FilterSegments extends React.Component { - constructor(props) { - super(props) +const defaultState = (segmentToFilter) => ({ + filter: { + status: '', + issue_category: null, + severity: null, + id_segment: segmentToFilter, + }, +}) - this.state = this.defaultState() - this.lqaNestedCategories = this.props.categories - this.severities = this.getSeverities() - } +const getSeverities = (categories) => { + const seen = new Set() + const severities = [] - defaultState() { - return { - filter: { - status: '', - issue_category: null, - severity: null, - id_segment: this.props.segmentToFilter, - }, + const collectSeverity = (sev) => { + const label = sev.get('label') + if (!seen.has(label)) { + seen.add(label) + severities.push(sev) } } - getSeverities() { - let severities = [] - let severitiesNames = [] - this.lqaNestedCategories.forEach((cat) => { - if (cat.get('subcategories').size === 0) { - cat.get('severities').forEach((sev) => { - if (severitiesNames.indexOf(sev.get('label')) === -1) { - severities.push(sev) - severitiesNames.push(sev.get('label')) - } - }) - } else { - cat.get('subcategories').forEach((subCat) => { - subCat.get('severities').forEach((sev) => { - if (severitiesNames.indexOf(sev.get('label')) === -1) { - severities.push(sev) - severitiesNames.push(sev.get('label')) - } - }) - }) - } - }) - return severities - } - - filterSelectChanged(type, value) { - let filter = {...this.state.filter} - filter[type] = value - if (type === 'status' && value === 'APPROVED-2') { - filter.revision_number = 2 - filter[type] = 'APPROVED2' - } else if (type === 'status' && value === 'APPROVED') { - filter.revision_number = 1 + categories.forEach((cat) => { + const subcategories = cat.get('subcategories') + if (subcategories.size === 0) { + cat.get('severities').forEach(collectSeverity) } else { - filter.revision_number = null + subcategories.forEach((subCat) => { + subCat.get('severities').forEach(collectSeverity) + }) } - this.setState({ - filter: filter, - }) + }) - this.props.applyFilter(filter) - } + return severities +} - resetStatusFilter() { - let filter = {...this.state.filter} - filter.status = '' - filter.revision_number = null - this.setState({ - filter: filter, - }) - setTimeout(() => { - this.props.applyFilter(this.state.filter) - }) - } - resetCategoryFilter() { - let filter = {...this.state.filter} - filter.issue_category = null - this.setState({ - filter: filter, - }) - setTimeout(() => { - this.props.applyFilter(this.state.filter) - }) - } +const getFilterClassName = (value) => + value && value !== '' ? 'filtered' : 'not-filtered' - resetSeverityFilter() { - let filter = {...this.state.filter} - filter.severity = null - this.setState({ - filter: filter, - }) - setTimeout(() => { - this.props.applyFilter(this.state.filter) - }) - } +const REVISION_OPTIONS = [ + {id: '1', name: 'Revise 1'}, + {id: '2', name: 'Revise 2'}, +] - filterIdSegmentChange(value) { - if (value && value !== '') { - this.filterSelectChanged('id_segment', value) - } else { - let filter = {...this.state.filter} - filter.id_segment = null - this.setState({ - filter: filter, - }) - setTimeout(() => { - this.props.applyFilter(this.state.filter) - }) - } - this.props.updateSegmentToFilter(value) - } +const FilterSegments = ({ + categories, + segmentToFilter, + applyFilter, + updateSegmentToFilter, + secondPassReviewEnabled, +}) => { + const [state, setState] = useState(() => defaultState(segmentToFilter)) + + const severities = useMemo(() => getSeverities(categories), [categories]) + + const updateFilter = useCallback( + (updates) => { + const filter = {...state.filter, ...updates} + setState({filter}) + setTimeout(() => applyFilter(filter)) + }, + [state.filter, applyFilter], + ) + + const filterSelectChanged = useCallback( + (type, value) => { + const updates = {[type]: value, revision_number: null} + + if (type === 'status') { + if (value === 'APPROVED-2') { + updates.revision_number = 2 + updates[type] = 'APPROVED 2' + } else if (value === 'APPROVED') { + updates.revision_number = 1 + } + } + + const filter = {...state.filter, ...updates} + setState({filter}) + applyFilter(filter) + }, + [state.filter, applyFilter], + ) - render() { - let statusOptions = config.searchable_statuses - .filter(({value}) => value !== 'REJECTED') - .map((item) => { - return { + const filterIdSegmentChange = useCallback( + (value) => { + if (value && value !== '') { + filterSelectChanged('id_segment', value) + } else { + updateFilter({id_segment: null}) + } + updateSegmentToFilter(value) + }, + [filterSelectChanged, updateFilter, updateSegmentToFilter], + ) + + const statusOptions = useMemo( + () => + config.searchable_statuses + .filter(({value}) => value !== 'REJECTED') + .map((item) => ({ name: ( <>
    {item.label} ), id: item.value, - } - }) - if (config.secondRevisionsCount) { - statusOptions.push({ - name: ( - <> -
    - APPROVED - - ), - id: 'APPROVED-2', - }) - } - let optionsCategory = this.lqaNestedCategories - .map((item) => { - return { - name: item.get('label'), - id: item.get('id'), - } - }) - .unshift({ - name: 'Any', - id: 'all', - }) - let optionsSeverities = this.severities.map((item) => { - return { + })), + [], + ) + + const optionsCategory = useMemo(() => { + const arr = categories.toJS().map((item) => ({ + name: item.label.replace(/\s*\(.*?\)\s*/g, ''), + id: String(item.id), + })) + arr.unshift({name: 'Any', id: 'all'}) + return arr + }, [categories]) + + const optionsSeverities = useMemo( + () => + severities.map((item) => ({ name: item.get('label'), id: item.get('label'), - } - }) - let statusFilterClass = - this.state.filter.status && this.state.filter.status !== '' - ? 'filtered' - : 'not-filtered' - let categoryFilterClass = - this.state.filter.issue_category && - this.state.filter.issue_category !== '' - ? 'filtered' - : 'not-filtered' - let severityFilterClass = - this.state.filter.severity && this.state.filter.severity !== '' - ? 'filtered' - : 'not-filtered' - return ( -
    - Filters by -
    -
    - -
    -
    - filterSelectChanged('status', value.id)} + activeOption={ + statusOptions.find((item) => item.id === filter.status) || + undefined + } + placeholder="Segment status" + checkSpaceToReverse={false} + showResetButton={true} + resetFunction={() => + updateFilter({status: '', revision_number: null}) + } + /> +
    + {secondPassReviewEnabled && ( +
    { - this.filterSelectChanged('severity', value.id) - }} - activeOption={ - optionsSeverities.find( - (item) => item.id == this.state.filter.severity, - ) || undefined + )} +
    + filterSelectChanged('severity', value.id)} + activeOption={ + optionsSeverities.find((item) => item.id == filter.severity) || + undefined + } + placeholder="Issue severity" + checkSpaceToReverse={false} + showResetButton={true} + resetFunction={() => updateFilter({severity: null})} + />
    - ) - } +
    + ) } export default FilterSegments diff --git a/public/js/components/quality_report/FilterSegments.test.js b/public/js/components/quality_report/FilterSegments.test.js new file mode 100644 index 0000000000..92985a52a8 --- /dev/null +++ b/public/js/components/quality_report/FilterSegments.test.js @@ -0,0 +1,204 @@ +import React from 'react' +import {render, screen, waitFor} from '@testing-library/react' +import userEvent from '@testing-library/user-event' +import Immutable from 'immutable' + +import FilterSegments from './FilterSegments' + +beforeEach(() => { + global.config = { + ...global.config, + searchable_statuses: [ + {value: 'NEW', label: 'NEW'}, + {value: 'DRAFT', label: 'DRAFT'}, + {value: 'TRANSLATED', label: 'TRANSLATED'}, + {value: 'APPROVED', label: 'APPROVED'}, + {value: 'REJECTED', label: 'REJECTED'}, + ], + } +}) + +const buildCategories = (overrides) => { + const defaults = [ + { + label: 'Typing', + id: 1, + severities: [ + {label: 'minor', penalty: 0.03}, + {label: 'major', penalty: 1}, + ], + subcategories: [], + }, + { + label: 'Translation', + id: 2, + severities: [ + {label: 'minor', penalty: 0.03}, + {label: 'major', penalty: 1}, + ], + subcategories: [], + }, + ] + return Immutable.fromJS(overrides || defaults) +} + +const defaultProps = { + applyFilter: jest.fn(), + updateSegmentToFilter: jest.fn(), + secondPassReviewEnabled: false, + segmentToFilter: null, +} + +const renderComponent = (propsOverrides = {}, categoriesOverrides) => { + const props = {...defaultProps, ...propsOverrides} + return render( + , + ) +} + +describe('FilterSegments', () => { + test('renders filter icon and input field', () => { + renderComponent() + + expect(screen.getByPlaceholderText('Id Segment')).toBeInTheDocument() + }) + + test('renders segment status filter', () => { + renderComponent() + + expect(screen.getByText('Segment status')).toBeInTheDocument() + }) + + test('renders issue category filter', () => { + renderComponent() + + expect(screen.getByText('Issue category')).toBeInTheDocument() + }) + + test('renders issue severity filter', () => { + renderComponent() + + expect(screen.getByText('Issue severity')).toBeInTheDocument() + }) + + test('does not render revision phase filter when secondPassReviewEnabled is false', () => { + renderComponent() + + expect(screen.queryByText('Revision phase')).not.toBeInTheDocument() + }) + + test('renders revision phase filter when secondPassReviewEnabled is true', () => { + renderComponent({secondPassReviewEnabled: true}) + + expect(screen.getByText('Revision phase')).toBeInTheDocument() + }) + + test('shows id_segment input with initial value from segmentToFilter prop', () => { + renderComponent({segmentToFilter: '42'}) + + const input = screen.getByPlaceholderText('Id Segment') + expect(input).toHaveValue('42') + }) + + test('id_segment input accepts user typing', async () => { + const user = userEvent.setup() + renderComponent() + + const input = screen.getByPlaceholderText('Id Segment') + await user.type(input, '5') + + expect(input).toHaveValue('5') + }) + + test('filters REJECTED from status options', async () => { + const user = userEvent.setup() + renderComponent() + + // Open the status dropdown + const statusPlaceholder = screen.getByText('Segment status') + await user.click(statusPlaceholder) + + await waitFor(() => { + expect(screen.getByText('NEW')).toBeInTheDocument() + }) + expect(screen.queryByText('REJECTED')).not.toBeInTheDocument() + expect(screen.getByText('TRANSLATED')).toBeInTheDocument() + expect(screen.getByText('APPROVED')).toBeInTheDocument() + }) + + test('category options include "Any" plus all categories', async () => { + const user = userEvent.setup() + renderComponent() + + // Open the category dropdown + const categoryPlaceholder = screen.getByText('Issue category') + await user.click(categoryPlaceholder) + + await waitFor(() => { + expect(screen.getByText('Any')).toBeInTheDocument() + }) + expect(screen.getByText('Typing')).toBeInTheDocument() + expect(screen.getByText('Translation')).toBeInTheDocument() + }) + + test('severity options are unique across categories', async () => { + const user = userEvent.setup() + renderComponent() + + // Open the severity dropdown + const severityPlaceholder = screen.getByText('Issue severity') + await user.click(severityPlaceholder) + + await waitFor(() => { + expect(screen.getAllByText('minor').length).toBeGreaterThanOrEqual(1) + }) + expect(screen.getAllByText('major').length).toBeGreaterThanOrEqual(1) + }) + + test('severity options collect from subcategories when present', async () => { + const user = userEvent.setup() + const categoriesWithSubs = [ + { + label: 'Accuracy', + id: 10, + severities: [], + subcategories: [ + { + label: 'Mistranslation', + id: 11, + severities: [ + {label: 'critical', penalty: 5}, + {label: 'major', penalty: 1}, + ], + }, + ], + }, + ] + renderComponent({}, categoriesWithSubs) + + // Open the severity dropdown + const severityPlaceholder = screen.getByText('Issue severity') + await user.click(severityPlaceholder) + + await waitFor(() => { + expect(screen.getByText('critical')).toBeInTheDocument() + }) + }) + + test('renders Revise 1 and Revise 2 options when secondPassReviewEnabled', async () => { + const user = userEvent.setup() + renderComponent({secondPassReviewEnabled: true}) + + // Open the revision phase dropdown + const revisionPlaceholder = screen.getByText('Revision phase') + await user.click(revisionPlaceholder) + + await waitFor(() => { + expect(screen.getByText('Revise 1')).toBeInTheDocument() + }) + expect(screen.getByText('Revise 2')).toBeInTheDocument() + }) +}) diff --git a/public/js/components/quality_report/JobSummary.js b/public/js/components/quality_report/JobSummary.js index 5856e0ad8d..aebb760907 100644 --- a/public/js/components/quality_report/JobSummary.js +++ b/public/js/components/quality_report/JobSummary.js @@ -4,36 +4,38 @@ import ProductionSummary from './ProductionSummary' import QualitySummaryTable from './QualitySummaryTable' import RevisionFeedback from './RevisionFeedback' -class JobSummary extends React.Component { - render() { - return ( -
    - {this.props.jobInfo ? ( - - ) : null} +export const JobSummary = ({ + jobInfo, + qualitySummary, + secondPassReviewEnabled, +}) => { + return ( +
    + {jobInfo ? ( + + ) : null} - {this.props.jobInfo && ( - - )} + {jobInfo && ( + + )} - {this.props.qualitySummary.get('feedback') ? ( - - ) : null} -
    - ) - } + {qualitySummary.get('feedback') ? ( + + ) : null} +
    + ) } export default JobSummary diff --git a/public/js/components/quality_report/ProductionSummary.js b/public/js/components/quality_report/ProductionSummary.js index 0ef290fc10..54f54757c2 100644 --- a/public/js/components/quality_report/ProductionSummary.js +++ b/public/js/components/quality_report/ProductionSummary.js @@ -3,9 +3,13 @@ import JobProgressBar from '../common/JobProgressBar' import {Popup} from 'semantic-ui-react' import HelpCircle from '../../../img/icons/HelpCircle' -class ProductionSummary extends React.Component { - getTimeToEdit = () => { - let time = parseInt(this.props.jobInfo.get('total_time_to_edit') / 1000) +export const ProductionSummary = ({ + qualitySummary, + jobInfo, + secondPassReviewEnabled, +}) => { + const getTimeToEdit = (type) => { + let time = parseInt(jobInfo.get('time_to_edit').get(type) / 1000) let hours = Math.floor(time / 3600) let minutes = Math.floor((time % 3600) / 60) let seconds = Math.floor((time % 3600) % 60) @@ -15,56 +19,54 @@ class ProductionSummary extends React.Component { .join(':') } - render() { - const {qualitySummary, jobInfo} = this.props - - const tooltipText = ( -
    - Matecat calculates the score as follows:
    -
    - (Tot. error points * 1000) / reviewed words -
    - Reviewed words = raw words - unmodified 101% matches -
    -
    - The score is compared to a max. amount of tolerated error points. - - Learn more - -
    - ) - const score = parseFloat(qualitySummary.get('score')) - const limit = qualitySummary.get('passfail') - ? parseInt(qualitySummary.getIn(['passfail', 'options', 'limit'])) - : 0 - const qualityOverall = qualitySummary.get('quality_overall') - const reviewedWordsCount = qualitySummary.get('total_reviewed_words_count') - const jobPassed = - qualityOverall !== null - ? qualityOverall !== 'fail' && reviewedWordsCount > 0 - : null - const jobPassedClass = - jobPassed === null || reviewedWordsCount === 0 - ? 'qr-norevision' - : jobPassed - ? 'qr-pass' - : 'qr-fail' - const translator = jobInfo.get('translator') - ? jobInfo.get('translator').get('email') - : 'Not assigned' - const stats = jobInfo.get('stats').toJS() - - return ( -
    + const tooltipText = ( +
    + Matecat calculates the score as follows:
    +
    + (Tot. error points * 1000) / reviewed words +
    + Reviewed words = raw words - unmodified 101% matches +
    +
    + The score is compared to a max. amount of tolerated error points. + + Learn more + +
    + ) + const score = parseFloat(qualitySummary.get('score')) + const limit = qualitySummary.get('passfail') + ? parseInt(qualitySummary.getIn(['passfail', 'options', 'limit'])) + : 0 + const qualityOverall = qualitySummary.get('quality_overall') + const reviewedWordsCount = qualitySummary.get('total_reviewed_words_count') + const jobPassed = + qualityOverall !== null + ? qualityOverall !== 'fail' && reviewedWordsCount > 0 + : null + const jobPassedClass = + jobPassed === null || reviewedWordsCount === 0 + ? 'qr-norevision' + : jobPassed + ? 'qr-pass' + : 'qr-fail' + const translator = jobInfo.get('translator') + ? jobInfo.get('translator').get('email') + : 'Not assigned' + const stats = jobInfo.get('stats').toJS() + + return ( +
    +
    ID: {jobInfo.get('id')}
    - {jobInfo.get('sourceTxt')} + {jobInfo.get('source')}
    @@ -72,14 +74,11 @@ class ProductionSummary extends React.Component {
    - {jobInfo.get('targetTxt')} + {jobInfo.get('target')}
    -
    (this.progressBar = bar)} - > +
    {Math.round( @@ -92,65 +91,55 @@ class ProductionSummary extends React.Component { %
    - -
    -
    Reviewed Words
    -
    - {reviewedWordsCount} +
    +
    +
    Reviewed Words
    +
    + {reviewedWordsCount} +
    -
    -
    -
    Translator
    -
    - {translator} -
    -
    - -
    -
    Time to edit
    -
    - {this.getTimeToEdit()}{' '} +
    +
    Translator
    +
    + {translator} +
    -
    -
    -
    PEE
    -
    - - {jobInfo.get('pee') ? Math.round(jobInfo.get('pee')) : 0}% - {' '} +
    +
    TTE Translate
    +
    + {getTimeToEdit('t')}{' '} +
    -
    - {config.project_type !== 'old' ? ( -
    +
    +
    TTE revise
    -
    - {score} + {getTimeToEdit('r1')}{' '} +
    +
    + {secondPassReviewEnabled && ( +
    +
    TTE revise 2
    +
    + {getTimeToEdit('r2')}{' '}
    - - {jobPassed === null || reviewedWordsCount === 0 ? ( -
    -
    Quality score
    -
    No revision
    -
    - ) : jobPassed ? ( -
    -
    Quality score
    -
    - Pass -
    -
    - ) : ( -
    -
    Quality score
    -
    - Fail -
    -
    - )}
    + )} +
    +
    PEE
    +
    + + {jobInfo.get('pee') ? Math.round(jobInfo.get('pee')) : 0}% + {' '} +
    +
    +
    +
    + {config.project_type !== 'old' ? ( +
    +
    - Threshold {limit} +
    + EPT score
    } /> +
    {score}
    - ) : null} -
    - ) - } +
    + {jobPassed === null || reviewedWordsCount === 0 ? ( +
    +
    No revision
    +
    + ) : jobPassed ? ( +
    +
    Pass
    +
    + ) : ( +
    +
    Fail
    +
    + )} +
    Threshold {limit}
    +
    +
    + ) : null} +
    + ) } export default ProductionSummary diff --git a/public/js/components/quality_report/QualitySummaryTable.js b/public/js/components/quality_report/QualitySummaryTable.js index 34e806d774..5e62c4301d 100644 --- a/public/js/components/quality_report/QualitySummaryTable.js +++ b/public/js/components/quality_report/QualitySummaryTable.js @@ -1,342 +1,332 @@ -import React from 'react' +import React, {useMemo, useCallback} from 'react' -import {isUndefined} from 'lodash' -import {isEqual} from 'lodash/lang' +function QualitySummaryTable({qualitySummary}) { + const lqaNestedCategories = useMemo( + () => qualitySummary.get('categories').sortBy((cat) => cat.get('id')), + [qualitySummary], + ) -class QualitySummaryTable extends React.Component { - constructor(props) { - super(props) - this.lqaNestedCategories = this.props.qualitySummary - .get('categories') - .sortBy((cat) => cat.get('id')) - const {severities, thereAreSubCategories, categoriesGroups} = - this.analyzeQualityModel() - this.thereAreSubCategories = thereAreSubCategories - this.severities = severities - this.categoriesGroups = categoriesGroups - } - analyzeQualityModel() { - let severities = [] - let severitiesFounded = [] - let categoriesGroups = [] + const {severities, thereAreSubCategories, categoriesGroups} = useMemo(() => { + const severities = [] + const seenLabels = new Set() + const categoriesGroups = [] let thereAreSubCategories = false - this.lqaNestedCategories.forEach((cat) => { + + const collectSeverity = (sev) => { + const label = sev.get('label') + if (!seenLabels.has(label)) { + severities.unshift(sev.toJS()) + seenLabels.add(label) + } + } + + lqaNestedCategories.forEach((cat) => { if (cat.get('subcategories').size === 0) { - let currentSeverities = cat.get('severities') - let groupFound = false - categoriesGroups.map((group) => { - if (isEqual(group[0].get('severities'), currentSeverities)) { - group.push(cat) - groupFound = true - } - }) - if (!groupFound) { + const currentSeverities = cat.get('severities') + const existingGroup = categoriesGroups.find((group) => + group[0].get('severities').equals(currentSeverities), + ) + if (existingGroup) { + existingGroup.push(cat) + } else { categoriesGroups.push([cat]) } - currentSeverities.forEach((sev) => { - if (severitiesFounded.indexOf(sev.get('label')) === -1) { - severities.unshift(sev.toJS()) - severitiesFounded.push(sev.get('label')) - } - }) + currentSeverities.forEach(collectSeverity) } else { thereAreSubCategories = true cat.get('subcategories').forEach((subCat) => { - subCat.get('severities').forEach((sev) => { - if (severitiesFounded.indexOf(sev.get('label')) === -1) { - severities.unshift(sev.toJS()) - severitiesFounded.push(sev.get('label')) - } - }) + subCat.get('severities').forEach(collectSeverity) }) } }) - const isSortProperyDefined = severities.every( - ({sort}) => typeof sort === 'number', - ) + const isSortDefined = severities.every(({sort}) => typeof sort === 'number') return { - severities: isSortProperyDefined - ? severities.sort((a, b) => (a.sort > b.sort ? 1 : -1)) + severities: isSortDefined + ? severities.sort((a, b) => a.sort - b.sort) : severities, thereAreSubCategories, categoriesGroups, } - } - getIssuesForCategory(categoryId) { - if (this.props.qualitySummary.size > 0) { - return this.props.qualitySummary - .get('revise_issues') - .find((item, key) => { - return parseInt(key) === parseInt(categoryId) - }) - } - } - getIssuesForCategoryWithSubcategory(category, sevLabel) { - let total = 0 - if (this.props.qualitySummary.size > 0) { + }, [lqaNestedCategories]) + + const getIssuesForCategory = useCallback( + (categoryId) => { + if (qualitySummary.size > 0) { + return qualitySummary + .get('revise_issues') + .find((_item, key) => parseInt(key) === parseInt(categoryId)) + } + }, + [qualitySummary], + ) + + const getIssuesForCategoryWithSubcategory = useCallback( + (category, sevLabel) => { + if (qualitySummary.size === 0) return 0 + const reviseIssues = qualitySummary.get('revise_issues') + if (category.subcategories.length > 0) { - category.subcategories.forEach((sub) => { - if ( - !isUndefined( - this.props.qualitySummary.get('revise_issues').get(sub.id), - ) && - this.props.qualitySummary - .get('revise_issues') - .get(sub.id) - .get('founds') - .get(sevLabel) - ) { - total += this.props.qualitySummary - .get('revise_issues') - .get(sub.id) - .get('founds') - .get(sevLabel) - } - }) - } else { - if (this.props.qualitySummary.get('revise_issues').get(category.id)) { - total = this.props.qualitySummary - .get('revise_issues') - .get(category.id) - .get('founds') - .get(sevLabel) - } + return category.subcategories.reduce((total, sub) => { + const issue = reviseIssues.get(sub.id) + const found = issue?.get('founds')?.get(sevLabel) + return total + (found || 0) + }, 0) } - } - return total - } - getCategorySeverities(categoryId) { - const cat = this.lqaNestedCategories.find( - (cat) => parseInt(categoryId) === parseInt(cat.get('id')), - ) - return cat.get('severities') - ? cat.get('severities') - : cat.get('subcategories').get(0).get('severities') - } - getHeader() { - let html = [] - this.severities.forEach((sev, index) => { - let item = ( -
    -
    {sev.label}
    -
    + + const issue = reviseIssues.get(category.id) + return issue ? issue.get('founds').get(sevLabel) || 0 : 0 + }, + [qualitySummary], + ) + + const getCategorySeverities = useCallback( + (categoryId) => { + const cat = lqaNestedCategories.find( + (cat) => parseInt(categoryId) === parseInt(cat.get('id')), ) - html.push(item) - }) - let totalScore = this.props.qualitySummary.get('total_issues_weight') - return ( + const severities = cat.get('severities') + return severities && severities.size > 0 + ? severities + : cat.get('subcategories').get(0).get('severities') + }, + [lqaNestedCategories], + ) + + const renderHeader = useCallback( + () => (
    -
    Issues
    - {html} -
    -
    Total error points
    -
    - {totalScore} -
    -
    +
    Categories
    +
    Severities
    + {severities.map( + (sev, i) => + i > 0 && ( +
    + ), + )} +
    Error Points
    - ) - } - getBody() { - let html = [] - this.categoriesGroups.forEach((group, i) => { - let groupHtml = [] + ), + [severities], + ) + + const renderBody = useCallback(() => { + const groupRows = categoriesGroups.flatMap((group, groupIndex) => { const sevGroup = group[0].get('severities') - groupHtml.push( -
    , - ) - //Some group can have not all severities - this.severities.forEach((sev) => { - let severityFind = sevGroup.find( - (currSev) => currSev.get('label') === sev.label, - ) - if (severityFind) { - groupHtml.push( -
    - Weight: {severityFind.get('penalty')} -
    , - ) - } else { - groupHtml.push( -
    , - ) - } - }) - const lineSeverityGroup = ( + + const severityWeightRow = (
    - {groupHtml} -
    -
    - ) - html.push(lineSeverityGroup) - group.forEach((cat, index) => { - let catHtml = [] - catHtml.push( -
    - {cat.get('label')} -
    , - ) - const totalIssues = this.getIssuesForCategory(cat.get('id')) - let catTotalWeightValue = 0 - this.severities.forEach((currentSev, i) => { - let severityFound = cat.get('severities').filter((sev) => { - return sev.get('label') === currentSev.label - }) - if ( - severityFound.size > 0 && - !isUndefined(totalIssues) && - totalIssues.get('founds').get(currentSev.label) - ) { - const issues = totalIssues.get('founds').get(currentSev.label) - const total = parseFloat( - (issues * severityFound.get(0).get('penalty')).toFixed(2), +
    + {/* Some groups may not have all severities */} + {severities.map((sev) => { + const severityMatch = sevGroup.find( + (currSev) => currSev.get('label') === sev.label, ) - catTotalWeightValue = catTotalWeightValue + total - catHtml.push( + return severityMatch ? (
    - {issues} -
    , + {sev.label}{' '} + (x{parseFloat(severityMatch.get('penalty'))}) +
    + ) : ( +
    ) - } else { - catHtml.push( -
    , + })} +
    +
    + ) + + const categoryRows = group + .filter((cat) => cat.get('label') !== 'Kudos') + .map((cat, catIndex) => { + const totalIssues = getIssuesForCategory(cat.get('id')) + let catTotalWeightValue = 0 + + const severityCells = severities.map((currentSev, sevIndex) => { + const severityFound = cat + .get('severities') + .filter((sev) => sev.get('label') === currentSev.label) + + if ( + severityFound.size > 0 && + totalIssues !== undefined && + totalIssues.get('founds').get(currentSev.label) + ) { + const issues = totalIssues.get('founds').get(currentSev.label) + catTotalWeightValue += parseFloat( + (issues * severityFound.get(0).get('penalty')).toFixed(2), + ) + return ( +
    + {issues} +
    + ) + } + return ( +
    ) - } - }) - let catTotalWeightHtml = ( -
    - {catTotalWeightValue} -
    - ) - if (cat.get('label') === 'Kudos') { - let issues = 0 - if (totalIssues && totalIssues.size > 0) { - cat.get('severities').forEach((sev) => { - issues += totalIssues.get('founds').get(sev.get('label')) - }) - } - catTotalWeightHtml = ( + }) + + return (
    -
    Total Kudos Points
    -
    {issues}
    +
    + {cat.get('label')} +
    + {severityCells} +
    + {catTotalWeightValue} +
    ) + }) + + return [severityWeightRow, ...categoryRows] + }) + + const severitiesTotal = severities.map((sev) => { + const totalSev = categoriesGroups.reduce((acc, group) => { + const catJs = group[0].toJS() + const totalIssues = getIssuesForCategory(catJs.id)?.toJS() + if (totalIssues?.founds[sev.label]) { + const severityDef = catJs.severities.find( + (s) => s.label === sev.label, + ) + return acc + totalIssues.founds[sev.label] * severityDef.penalty } - const line = ( -
    - {catHtml} - {catTotalWeightHtml} -
    - ) - html.push(line) - }) + return acc + }, 0) + return {label: sev.label, total: totalSev} }) - return
    {html}
    - } - getBodyWithSubcategories() { - let html = [] - this.lqaNestedCategories.forEach((cat, index) => { - let catHtml = [] - catHtml.push( -
    - {cat.get('label')} -
    , - ) + + const totalScore = qualitySummary.get('total_issues_weight') + + return ( +
    + {groupRows} +
    +
    Total
    + {severitiesTotal.map((sev, i) => ( +
    + {sev.total} +
    + ))} +
    + {totalScore} +
    +
    +
    + ) + }, [categoriesGroups, severities, getIssuesForCategory, qualitySummary]) + + const renderBodyWithSubcategories = useCallback(() => { + const rows = lqaNestedCategories.map((cat, index) => { let catTotalWeightValue = 0 - this.severities.forEach((currentSev, i) => { - let catSeverities = this.getCategorySeverities(cat.get('id')) - let severityFound = catSeverities.filter((sev) => { - return sev.get('label') === currentSev.label - }) - let totalIssues = this.getIssuesForCategoryWithSubcategory( + + const severityCells = severities.map((currentSev) => { + const catSeverities = getCategorySeverities(cat.get('id')) + const severityFound = catSeverities.filter( + (sev) => sev.get('label') === currentSev.label, + ) + const totalIssues = getIssuesForCategoryWithSubcategory( cat.toJS(), currentSev.label, ) + if (severityFound.size > 0 && totalIssues > 0) { - catTotalWeightValue = - catTotalWeightValue + - parseFloat( - (totalIssues * severityFound.get(0).get('penalty')).toFixed(2), - ) - catHtml.push( + catTotalWeightValue += parseFloat( + (totalIssues * severityFound.get(0).get('penalty')).toFixed(2), + ) + return (
    {totalIssues} -
    , - ) - } else { - catHtml.push( -
    , +
    ) } + return ( +
    + ) }) - let catTotalWeightHtml = ( -
    - {catTotalWeightValue} -
    - ) - let line = ( + + return (
    - {catHtml} - {catTotalWeightHtml} +
    + {cat.get('label')} +
    + {severityCells} +
    + {catTotalWeightValue} +
    ) - html.push(line) }) - return
    {html}
    - } - render() { - let htmlBody - let htmlHead = this.getHeader() - if (this.thereAreSubCategories) { - htmlBody = this.getBodyWithSubcategories() - } else { - htmlBody = this.getBody() - } - return ( -
    - {htmlHead} - {htmlBody} + return
    {rows}
    + }, [ + lqaNestedCategories, + severities, + getCategorySeverities, + getIssuesForCategoryWithSubcategory, + ]) + + const hasKudos = categoriesGroups.some( + (group) => group[0].get('label') === 'Kudos', + ) + + const kudosCount = hasKudos + ? qualitySummary + .get('revise_issues') + .find((item) => item.get('name') === 'Kudos') + ?.get('founds') + ?.get('Neutral') || 0 + : 0 + + return ( + <> +
    + {renderHeader()} + {thereAreSubCategories ? renderBodyWithSubcategories() : renderBody()}
    - ) - } + {hasKudos && ( +
    +
    Kudos
    +
    {kudosCount}
    +
    + )} + + ) } export default QualitySummaryTable diff --git a/public/js/components/quality_report/QualitySummaryTable.test.js b/public/js/components/quality_report/QualitySummaryTable.test.js new file mode 100644 index 0000000000..86215b2090 --- /dev/null +++ b/public/js/components/quality_report/QualitySummaryTable.test.js @@ -0,0 +1,356 @@ +import React from 'react' +import {render, screen} from '@testing-library/react' +import Immutable from 'immutable' + +import QualitySummaryTable from './QualitySummaryTable' + +// Helper to build an Immutable qualitySummary prop from plain JS +const buildQualitySummary = (overrides = {}) => { + const defaults = { + revision_number: 1, + feedback: null, + score: 0, + quality_overall: 'excellent', + total_issues_weight: 0, + total_reviewed_words_count: 100, + passfail: '', + categories: [ + { + label: 'Typing', + id: 1, + severities: [ + {label: 'minor', penalty: 0.03, sort: 1}, + {label: 'major', penalty: 1, sort: 2}, + ], + subcategories: [], + options: [], + }, + { + label: 'Translation', + id: 2, + severities: [ + {label: 'minor', penalty: 0.03, sort: 1}, + {label: 'major', penalty: 1, sort: 2}, + ], + subcategories: [], + options: [], + }, + { + label: 'Style', + id: 3, + severities: [ + {label: 'minor', penalty: 0.03, sort: 1}, + {label: 'major', penalty: 1, sort: 2}, + ], + subcategories: [], + options: [], + }, + ], + revise_issues: {}, + } + + return Immutable.fromJS({...defaults, ...overrides}) +} + +const defaultJobInfo = Immutable.fromJS({ + id: 123, + source: 'en-US', + target: 'it-IT', +}) + +const renderComponent = (qualitySummaryOverrides = {}) => { + const qualitySummary = buildQualitySummary(qualitySummaryOverrides) + return render( + , + ) +} + +describe('QualitySummaryTable', () => { + test('renders the header with category and severity columns', () => { + renderComponent() + + expect(screen.getByText('Categories')).toBeInTheDocument() + expect(screen.getByText('Severities')).toBeInTheDocument() + expect(screen.getByText('Error Points')).toBeInTheDocument() + }) + + test('renders all category labels', () => { + renderComponent() + + expect(screen.getByText('Typing')).toBeInTheDocument() + expect(screen.getByText('Translation')).toBeInTheDocument() + expect(screen.getByText('Style')).toBeInTheDocument() + }) + + test('renders total line', () => { + renderComponent() + + expect(screen.getByText('Total')).toBeInTheDocument() + }) + + test('renders severity weight labels with penalty multiplier', () => { + renderComponent() + + expect(screen.getByText('(x0.03)')).toBeInTheDocument() + expect(screen.getByText('(x1)')).toBeInTheDocument() + }) + + test('displays issue counts when revise_issues has data', () => { + renderComponent({ + revise_issues: { + 1: { + name: 'Typing', + founds: {minor: 3, major: 1}, + }, + 2: { + name: 'Translation', + founds: {minor: 0, major: 2}, + }, + }, + total_issues_weight: 2.09, + }) + + // Typing: minor=3, major=1 => error points = 3*0.03 + 1*1 = 1.09 + expect(screen.getByText('3')).toBeInTheDocument() + // Translation: major=2 => error points = 2*1 = 2 + expect(screen.getByText('2.09')).toBeInTheDocument() + }) + + test('renders zero total when no issues exist', () => { + renderComponent({total_issues_weight: 0}) + + const totalElements = screen.getAllByText('0') + expect(totalElements.length).toBeGreaterThan(0) + expect(screen.getByText('Total')).toBeInTheDocument() + }) + + test('renders with subcategories when present', () => { + // Note: getCategorySeverities checks `cat.get('severities')` for truthiness. + // An empty Immutable List is truthy, so parent categories should either omit + // severities or include the same severities as subcategories. + const categoriesData = Immutable.fromJS([ + { + label: 'Accuracy', + id: 10, + severities: [ + {label: 'minor', penalty: 1, sort: 1}, + {label: 'major', penalty: 5, sort: 2}, + ], + subcategories: [ + { + label: 'Mistranslation', + id: 11, + severities: [ + {label: 'minor', penalty: 1, sort: 1}, + {label: 'major', penalty: 5, sort: 2}, + ], + }, + { + label: 'Omission', + id: 12, + severities: [ + {label: 'minor', penalty: 1, sort: 1}, + {label: 'major', penalty: 5, sort: 2}, + ], + }, + ], + options: [], + }, + { + label: 'Fluency', + id: 20, + severities: [ + {label: 'minor', penalty: 1, sort: 1}, + {label: 'major', penalty: 5, sort: 2}, + ], + subcategories: [ + { + label: 'Grammar', + id: 21, + severities: [ + {label: 'minor', penalty: 1, sort: 1}, + {label: 'major', penalty: 5, sort: 2}, + ], + }, + ], + options: [], + }, + ]) + + // Build revise_issues with integer keys so .get(sub.id) works + const reviseIssues = Immutable.Map().set( + 11, + Immutable.fromJS({name: 'Mistranslation', founds: {minor: 2, major: 1}}), + ) + + const qualitySummary = Immutable.fromJS({ + revision_number: 1, + feedback: null, + score: 0, + quality_overall: 'excellent', + total_issues_weight: 7, + total_reviewed_words_count: 100, + passfail: '', + }) + .set('categories', categoriesData) + .set('revise_issues', reviseIssues) + + render( + , + ) + + // Parent categories should be displayed + expect(screen.getByText('Accuracy')).toBeInTheDocument() + expect(screen.getByText('Fluency')).toBeInTheDocument() + // Subcategory issues aggregated under Accuracy: minor=2, major=1 + expect(screen.getByText('2')).toBeInTheDocument() + expect(screen.getByText('1')).toBeInTheDocument() + }) + + test('renders Kudos section when Kudos category exists', () => { + renderComponent({ + categories: [ + { + label: 'Typing', + id: 1, + severities: [ + {label: 'minor', penalty: 0.03, sort: 1}, + {label: 'major', penalty: 1, sort: 2}, + ], + subcategories: [], + options: [], + }, + { + label: 'Kudos', + id: 99, + severities: [{label: 'Neutral', penalty: 0, sort: 0}], + subcategories: [], + options: [], + }, + ], + revise_issues: { + 99: {name: 'Kudos', founds: {Neutral: 5}}, + }, + }) + + expect(screen.getByText('Kudos')).toBeInTheDocument() + expect(screen.getByText('5')).toBeInTheDocument() + }) + + test('renders Kudos with 0 when no neutral issues found', () => { + renderComponent({ + categories: [ + { + label: 'Typing', + id: 1, + severities: [ + {label: 'minor', penalty: 0.03, sort: 1}, + {label: 'major', penalty: 1, sort: 2}, + ], + subcategories: [], + options: [], + }, + { + label: 'Kudos', + id: 99, + severities: [{label: 'Neutral', penalty: 0, sort: 0}], + subcategories: [], + options: [], + }, + ], + revise_issues: {}, + }) + + expect(screen.getByText('Kudos')).toBeInTheDocument() + // Kudos value should be 0 — find within the Kudos container + const kudosEl = screen.getByText('Kudos').closest('.qr-kudos') + expect(kudosEl).toHaveTextContent('0') + }) + + test('severities are sorted by sort property when defined', () => { + const qualitySummary = buildQualitySummary({ + categories: [ + { + label: 'Typing', + id: 1, + severities: [ + {label: 'critical', penalty: 5, sort: 3}, + {label: 'minor', penalty: 0.03, sort: 1}, + {label: 'major', penalty: 1, sort: 2}, + ], + subcategories: [], + options: [], + }, + ], + }) + + render( + , + ) + + // Verify the severity labels appear in sorted order (minor, major, critical) + const minorEl = screen.getByText('minor', {exact: false}) + const majorEl = screen.getByText('major', {exact: false}) + const criticalEl = screen.getByText('critical', {exact: false}) + + // Compare document order via compareDocumentPosition + expect( + minorEl.compareDocumentPosition(majorEl) & + Node.DOCUMENT_POSITION_FOLLOWING, + ).toBeTruthy() + expect( + majorEl.compareDocumentPosition(criticalEl) & + Node.DOCUMENT_POSITION_FOLLOWING, + ).toBeTruthy() + }) + + test('renders with different severity sets across categories', () => { + const qualitySummary = buildQualitySummary({ + categories: [ + { + label: 'Typing', + id: 1, + severities: [ + {label: 'minor', penalty: 0.03, sort: 1}, + {label: 'major', penalty: 1, sort: 2}, + ], + subcategories: [], + options: [], + }, + { + label: 'Style', + id: 3, + severities: [ + {label: 'minor', penalty: 0.1, sort: 1}, + {label: 'critical', penalty: 5, sort: 3}, + ], + subcategories: [], + options: [], + }, + ], + }) + + render( + , + ) + + // Should render without errors even with different severity groups + expect(screen.getByText('Typing')).toBeInTheDocument() + expect(screen.getByText('Style')).toBeInTheDocument() + // Both severity groups should show penalty multipliers + expect(screen.getByText('(x0.03)')).toBeInTheDocument() + expect(screen.getByText('(x0.1)')).toBeInTheDocument() + }) +}) diff --git a/public/js/components/quality_report/SegmentQR.js b/public/js/components/quality_report/SegmentQR.js index f9db22211c..f32fea02b1 100644 --- a/public/js/components/quality_report/SegmentQR.js +++ b/public/js/components/quality_report/SegmentQR.js @@ -1,6 +1,12 @@ -import React from 'react' +import React, { + useState, + useMemo, + useRef, + useEffect, + useCallback, + createRef, +} from 'react' import classnames from 'classnames' -import {isNull} from 'lodash/lang' import TextUtils from '../../utils/textUtils' import SegmentQRLine from './SegmentQRLine' @@ -13,644 +19,581 @@ import DraftMatecatUtils from '../segments/utils/DraftMatecatUtils' import SegmentQA from '../../../img/icons/SegmentQA' import AlertIcon from '../../../img/icons/AlertIcon' import InfoIcon from '../../../img/icons/InfoIcon' +import {Badge, BADGE_MODE, BADGE_TYPE} from '../common/Badge' +import Tooltip from '../common/Tooltip' +import ReviseIssuesIcon from '../../../img/icons/ReviseIssuesIcon' +import {Button, BUTTON_SIZE} from '../common/Button/Button' +import ChevronDown from '../../../img/icons/ChevronDown' +import ChevronUp from '../../../img/icons/ChevronUp' -class SegmentQR extends React.Component { - constructor(props) { - super(props) - this.source = this.props.segment.get('segment') - this.suggestion = this.props.segment.get('suggestion') - this.target = - !isNull(this.props.segment.get('last_translation')) && - this.props.segment.get('last_translation') - this.revise = - !isNull(this.props.segment.get('last_revisions')) && - this.props.segment.get('last_revisions').find((value) => { - return value.get('revision_number') === 1 - }) - this.revise2 = - !isNull(this.props.segment.get('last_revisions')) && - this.props.segment.get('last_revisions').find((value) => { - return value.get('revision_number') === 2 - }) - - this.revise = - this.revise && this.revise.size > 0 - ? this.revise.get('translation') - : false - this.revise2 = - this.revise2 && this.revise2.size > 0 - ? this.revise2.get('translation') - : false - //If second pass separate the issues - if (this.props.secondPassReviewEnabled) { - this.issuesR1 = this.props.segment.get('issues').filter((value) => { - return value.get('revision_number') === 1 - }) - this.issuesR2 = this.props.segment.get('issues').filter((value) => { - return value.get('revision_number') === 2 - }) - } +const QA_TYPES = ['ERROR', 'WARNING', 'INFO'] - this.state = { - translateDiffOn: - this.props.segment.get('last_translation') && - !isNull(this.props.segment.get('last_translation')) && - isNull(this.props.segment.get('last_revisions')), - reviseDiffOn: - !isNull(this.props.segment.get('last_revisions')) && - this.revise && - !this.revise2 && - this.props.segment.get('last_translation') && - !isNull(this.props.segment.get('last_translation')), - revise2DiffOn: - !isNull(this.props.segment.get('last_revisions')) && - this.revise2 && - (this.revise || !isNull(this.props.segment.get('last_translation'))), - htmlDiff: '', - automatedQaOpen: - this.props.segment.get('issues').size === 0 && - this.props.segment.get('warnings').get('total') > 0, - humanQaOpen: - !this.props.secondPassReviewEnabled && - this.props.segment.get('issues').size > 0, - r1QaOpen: this.props.revisionToShow === '1', - r2QaOpen: this.props.revisionToShow === '2', - } - this.state.htmlDiff = this.initializeDiff() - this.errorObj = { - types: { - TAGS: { - label: 'Tag mismatch', - }, - MISMATCH: { - label: 'Character mismatch', - }, - GLOSSARY: { - label: 'Glossary', - }, - }, - icons: { - ERROR: , - WARNING: , - INFO: , - }, - } - } +const QA_CATEGORY_LABELS = { + TAGS: 'Tag mismatch', + MISMATCH: 'Character mismatch', + GLOSSARY: 'Glossary', +} - initializeDiff() { - if (this.state.translateDiffOn) { - return this.getDiffPatch(this.suggestion, this.target) - } else if (this.state.reviseDiffOn) { - let revise = this.revise - return this.getDiffPatch(this.target, revise) - } else if (this.state.revise2DiffOn) { - let source = this.revise ? this.revise : this.target - return this.getDiffPatch(source, this.revise2) - } - } - openAutomatedQa() { - this.setState({ - automatedQaOpen: true, - humanQaOpen: false, - r1QaOpen: false, - r2QaOpen: false, - }) - } - openHumandQa() { - this.setState({ - automatedQaOpen: false, - humanQaOpen: true, - }) - } - openR1Qa() { - this.setState({ - automatedQaOpen: false, - r1QaOpen: true, - r2QaOpen: false, - }) +const QA_ICONS = { + ERROR: , + WARNING: , + INFO: , +} + +const strPadLeft = (value, pad, length) => + (new Array(length + 1).join(pad) + value).slice(-length) + +const decodeTextAndTransformTags = (text, isRtl) => { + if (text) { + // Fix for more than 2 followed spaces + const normalized = text.replace(/ {2}/gi, '  ') + return DraftMatecatUtils.transformTagsToHtml(normalized, isRtl) } - openR2Qa() { - this.setState({ - automatedQaOpen: false, - r1QaOpen: false, - r2QaOpen: true, - }) + return text +} + +const getRevisionTranslation = (revisions, revisionNumber) => { + if (revisions === null) return false + const found = revisions.find( + (value) => value.get('revision_number') === revisionNumber, + ) + return found && found.size > 0 ? found.get('translation') : false +} + +const getStatusBadgeType = (status) => { + const upper = status.toUpperCase() + if (upper === SEGMENTS_STATUS.NEW || upper === SEGMENTS_STATUS.DRAFT) { + return BADGE_TYPE.GREY } - getAutomatedQaHtml() { - let html = [] - let fnMap = (key, obj, type) => { - let item = ( -
    -
    - {this.errorObj.icons[type]} -
    -
    - {this.errorObj.types[key].label} ({obj.size}) -
    -
    - ) - html.push(item) - } - let details = this.props.segment - .get('warnings') - .get('details') - .get('issues_info') - if (details.get('ERROR').get('Categories').size > 0) { - details - .get('ERROR') - .get('Categories') - .entrySeq() - .forEach((item) => { - let key = item[0] - let value = item[1] - fnMap(key, value, 'ERROR') - }) - } - if (details.get('WARNING').get('Categories').size > 0) { - details - .get('WARNING') - .get('Categories') - .entrySeq() - .forEach((item) => { - let key = item[0] - let value = item[1] - fnMap(key, value, 'WARNING') - }) - } - if (details.get('INFO').get('Categories').size > 0) { - details - .get('INFO') - .get('Categories') - .entrySeq() - .forEach((item) => { - let key = item[0] - let value = item[1] - fnMap(key, value, 'INFO') - }) + if (upper === SEGMENTS_STATUS.APPROVED) return BADGE_TYPE.GREEN + if (upper === SEGMENTS_STATUS.APPROVED2) return BADGE_TYPE.PURPLE + return BADGE_TYPE.PRIMARY +} + +function SegmentQR({segment, urls, secondPassReviewEnabled, revisionToShow}) { + // Derived values from props + const source = useMemo(() => segment.get('segment'), [segment]) + const suggestion = useMemo(() => segment.get('suggestion'), [segment]) + const target = useMemo(() => { + const t = segment.get('last_translation') + return t !== null && t + }, [segment]) + const revise = useMemo( + () => getRevisionTranslation(segment.get('last_revisions'), 1), + [segment], + ) + const revise2 = useMemo( + () => getRevisionTranslation(segment.get('last_revisions'), 2), + [segment], + ) + + // If second pass, separate the issues by revision number + const issuesR1 = useMemo(() => { + if (!secondPassReviewEnabled) return null + return segment + .get('issues') + .filter((value) => value.get('revision_number') === 1) + }, [segment, secondPassReviewEnabled]) + + const issuesR2 = useMemo(() => { + if (!secondPassReviewEnabled) return null + return segment + .get('issues') + .filter((value) => value.get('revision_number') === 2) + }, [segment, secondPassReviewEnabled]) + + // State + const lastTranslation = segment.get('last_translation') + const lastRevisions = segment.get('last_revisions') + + const [translateDiffOn, setTranslateDiffOn] = useState( + lastTranslation !== null && lastTranslation && lastRevisions === null, + ) + const [reviseDiffOn, setReviseDiffOn] = useState( + lastRevisions !== null && + revise && + !revise2 && + lastTranslation !== null && + !!lastTranslation, + ) + const [revise2DiffOn, setRevise2DiffOn] = useState( + lastRevisions !== null && revise2 && (revise || lastTranslation !== null), + ) + const [htmlDiff, setHtmlDiff] = useState('') + const [automatedQaOpen, setAutomatedQaOpen] = useState( + segment.get('issues').size === 0 && + segment.get('warnings').get('total') > 0, + ) + const [humanQaOpen, setHumanQaOpen] = useState( + !secondPassReviewEnabled && segment.get('issues').size > 0, + ) + const [r1QaOpen, setR1QaOpen] = useState(revisionToShow === '1') + const [r2QaOpen, setR2QaOpen] = useState(revisionToShow === '2') + const [showHistory, setShowHistory] = useState(false) + + const issuesContainer = useRef(null) + + // Initialize diff on mount + useEffect(() => { + const getDiff = (src, tgt) => TextUtils.getDiffHtml(src, tgt) + if (translateDiffOn) { + setHtmlDiff(getDiff(suggestion, target)) + } else if (reviseDiffOn) { + setHtmlDiff(getDiff(target, revise)) + } else if (revise2DiffOn) { + setHtmlDiff(getDiff(revise || target, revise2)) } + // eslint-disable-next-line + }, []) - return html - } - getHumanQaHtml(issues) { - let html = [] - issues.map((issue, index) => { - let item = - html.push(item) - }) + useEffect(() => { + setR1QaOpen(revisionToShow === '1') + setR2QaOpen(revisionToShow === '2') + }, [revisionToShow]) - return html - } + // QA tab handlers + const openAutomatedQa = useCallback(() => { + setAutomatedQaOpen(true) + setHumanQaOpen(false) + setR1QaOpen(false) + setR2QaOpen(false) + }, []) + + const openHumanQa = useCallback(() => { + setAutomatedQaOpen(false) + setHumanQaOpen(true) + }, []) + + const openR1Qa = useCallback(() => { + setAutomatedQaOpen(false) + setR1QaOpen(true) + setR2QaOpen(false) + }, []) - showTranslateDiff() { - if (this.state.translateDiffOn) { - this.setState({ - translateDiffOn: false, - }) + const openR2Qa = useCallback(() => { + setAutomatedQaOpen(false) + setR1QaOpen(false) + setR2QaOpen(true) + }, []) + + // Diff toggle handlers + const showTranslateDiff = useCallback(() => { + if (translateDiffOn) { + setTranslateDiffOn(false) } else { - let diffHtml = this.getDiffPatch(this.suggestion, this.target) - this.setState({ - translateDiffOn: true, - reviseDiffOn: false, - revise2DiffOn: false, - htmlDiff: diffHtml, - }) + setTranslateDiffOn(true) + setReviseDiffOn(false) + setRevise2DiffOn(false) + setHtmlDiff(TextUtils.getDiffHtml(suggestion, target)) } - } - showReviseDiff() { - if (this.state.reviseDiffOn) { - this.setState({ - reviseDiffOn: false, - }) + }, [translateDiffOn, suggestion, target]) + + const showReviseDiff = useCallback(() => { + if (reviseDiffOn) { + setReviseDiffOn(false) } else { - let revise = this.revise - let textToDiff = this.target ? this.target : this.suggestion - let diffHtml = this.getDiffPatch(textToDiff, revise) - this.setState({ - translateDiffOn: false, - reviseDiffOn: true, - revise2DiffOn: false, - htmlDiff: diffHtml, - }) + setTranslateDiffOn(false) + setReviseDiffOn(true) + setRevise2DiffOn(false) + setHtmlDiff(TextUtils.getDiffHtml(target || suggestion, revise)) } - } - showRevise2Diff() { - if (this.state.revise2DiffOn) { - this.setState({ - revise2DiffOn: false, - }) + }, [reviseDiffOn, target, suggestion, revise]) + + const showRevise2Diff = useCallback(() => { + if (revise2DiffOn) { + setRevise2DiffOn(false) } else { - let revise2 = this.revise2 - let textToDiff = this.revise - ? this.revise - : this.target - ? this.target - : this.suggestion - let diffHtml = this.getDiffPatch(textToDiff, revise2) - this.setState({ - translateDiffOn: false, - reviseDiffOn: false, - revise2DiffOn: true, - htmlDiff: diffHtml, - }) - } - } - getWordsSpeed() { - let str_pad_left = function (string, pad, length) { - return (new Array(length + 1).join(pad) + string).slice(-length) - } - let time = parseInt(this.props.segment.get('secs_per_word')) - let minutes = Math.floor(time / 60) - let seconds = time - minutes * 60 - if (minutes > 0) { - return ( - str_pad_left(minutes, '0', 2) + - "'" + - str_pad_left(seconds, '0', 2) + - "''" + setTranslateDiffOn(false) + setReviseDiffOn(false) + setRevise2DiffOn(true) + setHtmlDiff( + TextUtils.getDiffHtml(revise || target || suggestion, revise2), ) - } else { - return str_pad_left(seconds, '0', 2) + "''" } - } - // getTimeToEdit() { - // let str_pad_left = function(string,pad,length) { - // return (new Array(length+1).join(pad)+string).slice(-length); - // }; - // let time = parseInt(this.props.segment.get("time_to_edit")/1000); - // let hours = Math.floor(time / 3600); - // let minutes = Math.floor( time / 60); - // let seconds = parseInt(time - minutes * 60); - // if (hours > 0 ) { - // return str_pad_left(hours,'0',2)+''+str_pad_left(minutes,'0',2)+"'"+str_pad_left(seconds,'0',2)+"''"; - // } else if (minutes > 0) { - // return str_pad_left(minutes,'0',2)+"'"+str_pad_left(seconds,'0',2)+"''"; - // } else { - // return str_pad_left(seconds,'0',2)+"''"; - // } - // - // } - getDiffPatch(source, text) { - return TextUtils.getDiffHtml(source, text) - } - openTranslateLink() { - window.open( - this.props.urls.get('translate_url') + '#' + this.props.segment.get('id'), - ) - } + }, [revise2DiffOn, revise, target, suggestion, revise2]) - openReviseLink(revise) { - if ( - typeof this.props.urls.get('revise_url') === 'string' || - this.props.urls.get('revise_url') instanceof String - ) { - window.open( - this.props.urls.get('revise_url') + '#' + this.props.segment.get('id'), - ) - } else { - let url = this.props.urls - .get('revise_urls') - .find((value) => { - return value.get('revision_number') === revise - }) - .get('url') - window.open(url + '#' + this.props.segment.get('id')) - } - } + const getAutomatedQaHtml = useCallback(() => { + const details = segment.get('warnings').get('details').get('issues_info') - decodeTextAndTransformTags(text, isRtl) { - if (text) { - // Fix for more than 2 followed spaces - text = text.replace(/ /gi, '  ') - let decodedText = DraftMatecatUtils.transformTagsToHtml(text, isRtl) - return decodedText - } - return text - } - allowHTML(string) { - return {__html: string} - } - componentDidUpdate(prevProps) { - if (prevProps.revisionToShow !== this.props.revisionToShow) { - this.setState({ - r1QaOpen: this.props.revisionToShow === '1', - r2QaOpen: this.props.revisionToShow === '2', - }) - } - } + return QA_TYPES.flatMap((type) => { + const categories = details.get(type).get('Categories') + if (categories.size === 0) return [] + return categories + .entrySeq() + .map(([key, value]) => ( +
    +
    + {QA_ICONS[type]} +
    +
    + {QA_CATEGORY_LABELS[key]} ({value.size}) +
    +
    + )) + .toArray() + }) + }, [segment]) - render() { - let source = this.decodeTextAndTransformTags( - this.source, - config.isSourceRTL, - ) - let suggestion = this.decodeTextAndTransformTags( - this.suggestion, - config.isTargetRTL, - ) - let target = - this.target && - this.decodeTextAndTransformTags(this.target, config.isTargetRTL) - let revise = - this.revise && - this.decodeTextAndTransformTags(this.revise, config.isTargetRTL) - let revise2 = - this.revise2 && - this.decodeTextAndTransformTags(this.revise2, config.isTargetRTL) - - if (this.state.translateDiffOn) { - target = this.decodeTextAndTransformTags( - this.state.htmlDiff, - config.isTargetRTL, - ) - } + const renderHumanQaIssues = useCallback( + (issues) => + issues + .map((issue, index) => ( + + )) + .toArray(), + [], + ) - if (this.state.reviseDiffOn) { - revise = this.decodeTextAndTransformTags( - this.state.htmlDiff, - config.isTargetRTL, - ) + const getWordsSpeed = useCallback(() => { + const time = parseInt(segment.get('secs_per_word')) + const minutes = Math.floor(time / 60) + const seconds = time - minutes * 60 + if (minutes > 0) { + return `${strPadLeft(minutes, '0', 2)}'${strPadLeft(seconds, '0', 2)}''` } + return `${strPadLeft(seconds, '0', 2)}''` + }, [segment]) - if (this.state.revise2DiffOn) { - revise2 = this.decodeTextAndTransformTags( - this.state.htmlDiff, - config.isTargetRTL, - ) - } + const openTranslateLink = useCallback(() => { + window.open(`${urls.get('translate_url')}#${segment.get('id')}`) + }, [urls, segment]) - let sourceClass = classnames({ - 'segment-container': true, - 'qr-source': true, - 'rtl-lang': config.isSourceRTL, - }) + const openReviseLink = useCallback( + (reviseNum) => { + const reviseUrl = urls.get('revise_url') + if (typeof reviseUrl === 'string' || reviseUrl instanceof String) { + window.open(`${reviseUrl}#${segment.get('id')}`) + } else { + const url = urls + .get('revise_urls') + .find((value) => value.get('revision_number') === reviseNum) + .get('url') + window.open(`${url}#${segment.get('id')}`) + } + }, + [urls, segment], + ) - let segmentBodyClass = classnames({ - 'qr-segment-body': true, - 'qr-diff-on': - this.state.translateDiffOn || - this.state.reviseDiffOn || - this.state.revise2DiffOn, - }) - let suggestionClasses = classnames({ - 'segment-container': true, - 'qr-suggestion': true, - 'shadow-1': - this.state.translateDiffOn || - (this.state.reviseDiffOn && !this.target) || - (this.state.revise2DiffOn && !this.revise && !this.target), - 'rtl-lang': config.isTargetRTL, - }) - let translateClasses = classnames({ - 'segment-container': true, - 'qr-translated': true, - 'shadow-1': - this.state.translateDiffOn || - this.state.reviseDiffOn || - (this.state.revise2DiffOn && !this.revise), - 'rtl-lang': config.isTargetRTL, - }) - let revisedClasses = classnames({ - 'segment-container': true, - 'qr-revised': true, - 'shadow-1': this.state.reviseDiffOn || this.state.revise2DiffOn, - 'rtl-lang': config.isTargetRTL, + const renderSegmentHistory = () => { + const history = segment + .get('history') + .toJS() + .filter((elem) => elem.status) + return history.map((elem, index) => { + return ( +
    +
    +
    + {index < history.length - 1 && ( +
    + )} + {elem.status === SEGMENTS_STATUS.APPROVED2 + ? '2nd Revision' + : elem.status.charAt(0).toUpperCase() + + elem.status.toLowerCase().slice(1)} +
    +
    + {elem.date.replaceAll('-', '/')} +
    +
    + {elem.issues.length > 0 && ( + + {elem.issues.map((issue) => ( +
    + {issue.issue_category}:{' '} + + {issue.issue_severity} + +
    + ))} +
    + } + > +
    + + + Issues + +
    + + )} +
    + ) }) - let revised2Classes = classnames({ - 'segment-container': true, - 'qr-revised': true, - 'qr-revised-2ndpass': true, - 'shadow-1': this.state.revise2DiffOn, + } + + // Render logic + const renderedSource = decodeTextAndTransformTags(source, config.isSourceRTL) + const renderedSuggestion = decodeTextAndTransformTags( + suggestion, + config.isTargetRTL, + ) + const renderedTarget = translateDiffOn + ? decodeTextAndTransformTags(htmlDiff, config.isTargetRTL) + : target && decodeTextAndTransformTags(target, config.isTargetRTL) + const renderedRevise = reviseDiffOn + ? decodeTextAndTransformTags(htmlDiff, config.isTargetRTL) + : revise && decodeTextAndTransformTags(revise, config.isTargetRTL) + const renderedRevise2 = revise2DiffOn + ? decodeTextAndTransformTags(htmlDiff, config.isTargetRTL) + : revise2 && decodeTextAndTransformTags(revise2, config.isTargetRTL) + + const isDiffOn = translateDiffOn || reviseDiffOn || revise2DiffOn + const sourceClass = classnames('segment-container', 'qr-source', { + 'rtl-lang': config.isSourceRTL, + }) + const segmentBodyClass = classnames('qr-segment-body', { + 'qr-diff-on': isDiffOn, + }) + const suggestionClasses = classnames('segment-container', 'qr-suggestion', { + 'shadow-1': + translateDiffOn || + (reviseDiffOn && !target) || + (revise2DiffOn && !revise && !target), + 'rtl-lang': config.isTargetRTL, + }) + const translateClasses = classnames('segment-container', 'qr-translated', { + 'shadow-1': translateDiffOn || reviseDiffOn || (revise2DiffOn && !revise), + 'rtl-lang': config.isTargetRTL, + }) + const revisedClasses = classnames('segment-container', 'qr-revised', { + 'shadow-1': reviseDiffOn || revise2DiffOn, + 'rtl-lang': config.isTargetRTL, + }) + const revised2Classes = classnames( + 'segment-container', + 'qr-revised', + 'qr-revised-2ndpass', + { + 'shadow-1': revise2DiffOn, 'rtl-lang': config.isTargetRTL, - }) - return ( -
    -
    -
    {this.props.segment.get('id')}
    -
    -
    -
    - Analysis:{' '} - - { - ANALYSIS_BUCKETS_LABELS[ - this.props.segment.get('match_type') - ] - } - -
    -
    - Secs/Word: {this.getWordsSpeed()} -
    - {/*
    Time to edit: {this.getTimeToEdit()}
    */} -
    - PEE: {this.props.segment.get('pee')}% -
    + }, + ) + + const issuesCount = segment.get('issues').size + const warningsTotal = segment.get('warnings').get('total') + const isQaVisible = automatedQaOpen || humanQaOpen || r1QaOpen || r2QaOpen + + return ( +
    +
    +
    {segment.get('id')}
    +
    +
    +
    + Analysis:{' '} + {ANALYSIS_BUCKETS_LABELS[segment.get('match_type')]}
    -
    -
    -
    Segment status
    -
    - - {this.props.segment.get('status') === SEGMENTS_STATUS.APPROVED2 - ? SEGMENTS_STATUS.APPROVED - : this.props.segment.get('status')} - +
    + Secs/Word: {getWordsSpeed()} +
    +
    + PEE: {segment.get('pee')}%
    - -
    +
    +
    Segment status
    +
    + + {segment.get('status') === SEGMENTS_STATUS.APPROVED2 + ? SEGMENTS_STATUS.APPROVED.toLowerCase() + : segment.get('status').toLowerCase()} + +
    +
    +
    +
    + + + {segment.get('last_translation') ? ( + ) : null} + {segment.get('last_revisions') !== null && revise ? ( openReviseLink(1)} + text={renderedRevise} + showDiffButton={true} + onClickDiff={showReviseDiff} + diffActive={reviseDiffOn} + showIceMatchInfo={target === null} + tte={segment.get('time_to_edit_revise')} + showIsPretranslated={ + segment.get('is_pre_translated') && !segment.get('ice_locked') + } + rev={1} /> - - {this.props.segment.get('last_translation') ? ( - - ) : null} - {!isNull(this.props.segment.get('last_revisions')) && revise ? ( - - ) : null} - {!isNull(this.props.segment.get('last_revisions')) && revise2 ? ( - - ) : null} - {this.state.automatedQaOpen || - this.state.humanQaOpen || - this.state.r1QaOpen || - this.state.r2QaOpen ? ( -
    -
    - QA -
    - {this.props.segment.get('issues').size > 0 && - !this.props.secondPassReviewEnabled ? ( -
    0 - ? '' - : 'no-hover') - } - onClick={this.openHumandQa.bind(this)} - > - Human ({this.props.segment.get('issues').size}) -
    - ) : null} - - {this.issuesR1 && - this.issuesR1.size > 0 && - this.props.secondPassReviewEnabled ? ( -
    - R1 ({this.issuesR1.size}) -
    - ) : null} - - {this.issuesR2 && - this.issuesR2.size > 0 && - this.props.secondPassReviewEnabled ? ( -
    - R2 ({this.issuesR2.size}) -
    - ) : null} - - {this.props.segment.get('warnings').get('total') > 0 ? ( -
    0 - ? '' - : 'no-hover') - } - onClick={this.openAutomatedQa.bind(this)} - > - Automated - - {' '} - ({this.props.segment.get('warnings').get('total')}) - -
    - ) : null} -
    -
    -
    - (this.issuesContainer = issueContainer) - } - > - {this.state.automatedQaOpen ? ( -
    - {this.getAutomatedQaHtml()} + ) : null} + {segment.get('last_revisions') !== null && revise2 ? ( + openReviseLink(2)} + text={renderedRevise2} + showDiffButton={true} + onClickDiff={showRevise2Diff} + diffActive={revise2DiffOn} + showIceMatchInfo={target === null && revise === null} + tte={segment.get('time_to_edit_revise_2')} + showIsPretranslated={ + segment.get('is_pre_translated') && !segment.get('ice_locked') + } + rev={2} + /> + ) : null} + {isQaVisible && ( +
    +
    + QA +
    + {issuesCount > 0 && !secondPassReviewEnabled && ( +
    + Human ({issuesCount})
    - ) : null} - - {this.state.humanQaOpen ? ( -
    - {this.getHumanQaHtml(this.props.segment.get('issues'))} + )} + {issuesR1?.size > 0 && secondPassReviewEnabled && ( +
    + R1 ({issuesR1.size})
    - ) : null} - - {this.state.r1QaOpen && this.issuesR1 ? ( -
    - {this.getHumanQaHtml(this.issuesR1)} + )} + {issuesR2?.size > 0 && secondPassReviewEnabled && ( +
    + R2 ({issuesR2.size})
    - ) : null} - {this.state.r2QaOpen && this.issuesR2 ? ( -
    - {this.getHumanQaHtml(this.issuesR2)} + )} + {warningsTotal > 0 && ( +
    + Automated + ({warningsTotal})
    - ) : null} + )}
    - ) : null} -
    +
    + {automatedQaOpen && ( +
    + {getAutomatedQaHtml()} +
    + )} + {humanQaOpen && ( +
    + {renderHumanQaIssues(segment.get('issues'))} +
    + )} + {r1QaOpen && issuesR1 && ( +
    + {renderHumanQaIssues(issuesR1)} +
    + )} + {r2QaOpen && issuesR2 && ( +
    + {renderHumanQaIssues(issuesR2)} +
    + )} +
    + {(segment.get('history')?.size ?? 0) > 0 ? ( + !showHistory ? ( + + ) : ( + + ) + ) : null} +
    + )} + {(segment.get('history')?.size ?? 0) > 0 && showHistory && ( +
    {renderSegmentHistory()}
    + )}
    - ) - } +
    + ) } export default SegmentQR diff --git a/public/js/components/quality_report/SegmentQR.test.js b/public/js/components/quality_report/SegmentQR.test.js new file mode 100644 index 0000000000..37d764c713 --- /dev/null +++ b/public/js/components/quality_report/SegmentQR.test.js @@ -0,0 +1,329 @@ +import React from 'react' +import {render, screen} from '@testing-library/react' +import userEvent from '@testing-library/user-event' +import Immutable from 'immutable' + +import SegmentQR from './SegmentQR' + +// Mock dependencies +jest.mock('../../utils/textUtils', () => ({ + getDiffHtml: jest.fn((source, target) => `${target}`), +})) + +jest.mock( + '../segments/utils/DraftMatecatUtils', + () => ({ + transformTagsToHtml: jest.fn((text) => text), + }), + {virtual: true}, +) + +beforeEach(() => { + global.config = { + ...global.config, + isSourceRTL: false, + isTargetRTL: false, + } + jest.spyOn(window, 'open').mockImplementation(() => {}) +}) + +afterEach(() => { + window.open.mockRestore() +}) + +const buildSegment = (overrides = {}) => { + const defaults = { + id: 100, + segment: 'Hello world', + suggestion: 'Ciao mondo', + suggestion_match: '85', + suggestion_source: 'MT', + match_type: 'MT', + last_translation: null, + last_revisions: null, + status: 'TRANSLATED', + raw_word_count: '5.00', + secs_per_word: 12, + pee: 35, + time_to_edit: 500, + time_to_edit_translation: null, + time_to_edit_revise: null, + time_to_edit_revise_2: null, + ice_locked: '0', + ice_modified: false, + is_pre_translated: false, + issues: [], + warnings: { + total: 0, + details: { + issues_info: { + ERROR: {Categories: {}}, + WARNING: {Categories: {}}, + INFO: {Categories: {}}, + }, + }, + }, + } + return Immutable.fromJS({...defaults, ...overrides}) +} + +const defaultUrls = Immutable.fromJS({ + translate_url: 'https://example.com/translate/job', + revise_urls: [ + {revision_number: 1, url: 'https://example.com/revise1/job'}, + {revision_number: 2, url: 'https://example.com/revise2/job'}, + ], +}) + +const renderComponent = (segmentOverrides = {}, extraProps = {}) => { + const segment = buildSegment(segmentOverrides) + return render( + , + ) +} + +describe('SegmentQR', () => { + test('renders segment ID', () => { + renderComponent() + expect(screen.getByText('100')).toBeInTheDocument() + }) + + test('renders segment status', () => { + renderComponent() + expect(screen.getByText('translated')).toBeInTheDocument() + }) + + test('renders production stats', () => { + renderComponent() + expect(screen.getByText('Machine Translation')).toBeInTheDocument() + expect(screen.getByText("12''")).toBeInTheDocument() + expect(screen.getByText('35%')).toBeInTheDocument() + }) + + test('renders source and suggestion lines', () => { + renderComponent() + expect(screen.getByText('Source')).toBeInTheDocument() + expect(screen.getByText('Suggestion')).toBeInTheDocument() + }) + + test('does not render translation line when last_translation is null', () => { + renderComponent() + expect(screen.queryByText('Translation')).not.toBeInTheDocument() + }) + + test('renders translation line when last_translation is set', () => { + renderComponent({last_translation: 'Ciao mondo tradotto'}) + expect(screen.getByText('Translation')).toBeInTheDocument() + }) + + test('does not render revision line when last_revisions is null', () => { + renderComponent() + expect(screen.queryByText('Revision')).not.toBeInTheDocument() + }) + + test('renders revision line when R1 revision exists', () => { + renderComponent({ + last_translation: 'Tradotto', + last_revisions: [{revision_number: 1, translation: 'Revisione 1'}], + }) + expect(screen.getByText('Revision')).toBeInTheDocument() + }) + + test('renders 2nd revision line when R2 revision exists', () => { + renderComponent({ + last_translation: 'Tradotto', + last_revisions: [ + {revision_number: 1, translation: 'Revisione 1'}, + {revision_number: 2, translation: 'Revisione 2'}, + ], + }) + expect(screen.getByText('Revision')).toBeInTheDocument() + expect(screen.getByText('2nd Revision')).toBeInTheDocument() + }) + + test('renders words per second with minutes and seconds', () => { + renderComponent({secs_per_word: 125}) + expect(screen.getByText("02'05''")).toBeInTheDocument() + }) + + test('renders words per second with only seconds', () => { + renderComponent({secs_per_word: 8}) + expect(screen.getByText("08''")).toBeInTheDocument() + }) + + test('diff button toggles diff view on translation', async () => { + const user = userEvent.setup() + renderComponent({ + last_translation: 'Ciao mondo tradotto', + suggestion: 'Ciao mondo', + }) + + const diffButtons = screen.getAllByTitle('Show Diff') + expect(diffButtons.length).toBeGreaterThan(0) + + // Click the diff button for translation + await user.click(diffButtons[0]) + }) + + test('renders automated QA when warnings exist and no issues', () => { + renderComponent({ + warnings: { + total: 2, + details: { + issues_info: { + ERROR: { + Categories: { + TAGS: ['tag1', 'tag2'], + }, + }, + WARNING: {Categories: {}}, + INFO: {Categories: {}}, + }, + }, + }, + }) + + expect(screen.getByText('QA')).toBeInTheDocument() + expect(screen.getByText(/Automated/)).toBeInTheDocument() + expect(screen.getByText('Tag mismatch')).toBeInTheDocument() + }) + + test('renders human QA when issues exist', () => { + renderComponent({ + issues: [ + { + issue_id: 1, + issue_category: 'Accuracy', + issue_severity: 'Major', + revision_number: 1, + comments: [], + target_text: '', + }, + ], + }) + + expect(screen.getByText('QA')).toBeInTheDocument() + expect(screen.getByText(/Human/)).toBeInTheDocument() + expect(screen.getByText(/Accuracy/)).toBeInTheDocument() + }) + + test('renders R1 and R2 QA tabs when secondPassReviewEnabled', () => { + renderComponent( + { + issues: [ + { + issue_id: 1, + issue_category: 'Accuracy', + issue_severity: 'Major', + revision_number: 1, + comments: [], + target_text: '', + }, + { + issue_id: 2, + issue_category: 'Fluency', + issue_severity: 'Minor', + revision_number: 2, + comments: [], + target_text: '', + }, + ], + }, + {secondPassReviewEnabled: true, revisionToShow: '1'}, + ) + + expect(screen.getByText(/R1/)).toBeInTheDocument() + expect(screen.getByText(/R2/)).toBeInTheDocument() + }) + + test('clicking R2 tab shows R2 issues', async () => { + const user = userEvent.setup() + renderComponent( + { + issues: [ + { + issue_id: 1, + issue_category: 'Accuracy', + issue_severity: 'Major', + revision_number: 1, + comments: [], + target_text: '', + }, + { + issue_id: 2, + issue_category: 'Fluency', + issue_severity: 'Minor', + revision_number: 2, + comments: [], + target_text: '', + }, + ], + }, + {secondPassReviewEnabled: true, revisionToShow: '1'}, + ) + + const r2Button = screen.getByText(/R2/) + await user.click(r2Button) + expect(screen.getByText(/Fluency/)).toBeInTheDocument() + }) + + test('opens translate link on label click', async () => { + const user = userEvent.setup() + renderComponent({last_translation: 'Tradotto'}) + + await user.click(screen.getByText('Translation')) + expect(window.open).toHaveBeenCalledWith( + 'https://example.com/translate/job#100', + ) + }) + + test('opens revise link with revise_urls list', async () => { + const user = userEvent.setup() + renderComponent({ + last_translation: 'Tradotto', + last_revisions: [{revision_number: 1, translation: 'Revisione'}], + }) + + await user.click(screen.getByText('Revision')) + expect(window.open).toHaveBeenCalledWith( + 'https://example.com/revise1/job#100', + ) + }) + + test('renders APPROVED2 status as approved', () => { + renderComponent({status: 'APPROVED2'}) + expect(screen.getByText('approved')).toBeInTheDocument() + }) + + test('does not render QA section when no issues and no warnings', () => { + renderComponent() + expect(screen.queryByText('QA')).not.toBeInTheDocument() + }) + + test('renders automated QA with WARNING categories', () => { + renderComponent({ + warnings: { + total: 1, + details: { + issues_info: { + ERROR: {Categories: {}}, + WARNING: { + Categories: { + MISMATCH: ['mismatch1'], + }, + }, + INFO: {Categories: {}}, + }, + }, + }, + }) + + expect(screen.getByText('Character mismatch')).toBeInTheDocument() + }) +}) diff --git a/public/js/components/quality_report/SegmentQRIssue.js b/public/js/components/quality_report/SegmentQRIssue.js index 2b718421d5..7f2d4fb039 100644 --- a/public/js/components/quality_report/SegmentQRIssue.js +++ b/public/js/components/quality_report/SegmentQRIssue.js @@ -2,6 +2,8 @@ import React from 'react' import moment from 'moment' import {isUndefined} from 'lodash' import {Popup} from 'semantic-ui-react' +import {Button, BUTTON_MODE, BUTTON_SIZE} from '../common/Button/Button' +import CommentsSquareIconFilled from '../../../img/icons/CommentsSquareIconFilled' class SegmentQRIssue extends React.Component { generateHtmlCommentLines(issue) { @@ -80,18 +82,13 @@ class SegmentQRIssue extends React.Component { hoverable position="bottom right" trigger={ -
    (this.comments = comments)} + -
    + + } >
    0 && suggestionMatch <= 99 - ? 'per-orange' + ? BADGE_TYPE.ORANGE : suggestionMatch === 0 - ? 'per-red' + ? BADGE_TYPE.RED : '' } @@ -120,16 +121,14 @@ const SegmentQRLine = ({ {showSuggestionSource ? (
    -
    - {!segment.get('suggestion_source') ? ( - {suggestionMatch}% - ) : segment.get('suggestion_source') !== 'MT' ? ( - - {segment.get('suggestion_source')} - {suggestionMatch}% - - ) : ( - {segment.get('suggestion_source')} - )} +
    + + {!segment.get('suggestion_source') + ? suggestionMatch + '%' + : segment.get('suggestion_source') !== 'MT' + ? `${segment.get('suggestion_source')} - ${suggestionMatch}%` + : segment.get('suggestion_source')} +
    ) : null} diff --git a/public/js/components/quality_report/SegmentsDetailsContainer.js b/public/js/components/quality_report/SegmentsDetailsContainer.js index f5c26a8c4e..149ebfaf7b 100644 --- a/public/js/components/quality_report/SegmentsDetailsContainer.js +++ b/public/js/components/quality_report/SegmentsDetailsContainer.js @@ -1,47 +1,42 @@ -import React from 'react' +import React, {useState, useCallback, useEffect, useRef} from 'react' import {debounce} from 'lodash' import Filters from './FilterSegments' import FileDetails from './FileDetails' import QualityReportActions from '../../actions/QualityReportActions' +import {SPINNER_LOADER_SIZE, SpinnerLoader} from '../common/SpinnerLoader' -class SegmentsDetails extends React.Component { - constructor(props) { - super(props) - this.state = { - filter: null, - } - } - getFiles() { +function SegmentsDetails(props) { + const [filter, setFilter] = useState(null) + const scrollDebounceFnRef = useRef(null) + + const getFiles = useCallback(() => { let files = [] - if (this.props.files) { - this.props.files.forEach((fileObj) => { + if (props.files) { + props.files.forEach((fileObj) => { let file = ( ) files.push(file) }) } return files - } - - scrollDebounceFn() { - let self = this - return debounce(function () { - self.onScroll() - }, 200) - } + }, [ + props.files, + props.revisionToShow, + props.segmentsFiles, + props.urls, + props.secondPassReviewEnabled, + ]) - onScroll() { + const onScroll = useCallback(() => { let scrollableHeight = document.getElementById('qr-root').scrollHeight - document.getElementById('qr-root').clientHeight @@ -50,76 +45,74 @@ class SegmentsDetails extends React.Component { if ( document.getElementById('qr-root').scrollTop + modifier > scrollableHeight && - this.props.moreSegments + props.moreSegments ) { - QualityReportActions.getMoreQRSegments( - this.state.filter, - this.props.lastSegment, - ) + QualityReportActions.getMoreQRSegments(filter, props.lastSegment) } - } - filterSegments(filter) { - this.setState({ - filter: filter, - }) - QualityReportActions.filterSegments(filter, null) - } + }, [filter, props.moreSegments, props.lastSegment]) - componentDidMount() { - document - .getElementById('qr-root') - .addEventListener('scroll', this.scrollDebounceFn(), false) - } + // Debounced scroll handler + useEffect(() => { + scrollDebounceFnRef.current = debounce(onScroll, 200) + const qrRoot = document.getElementById('qr-root') + if (qrRoot) { + qrRoot.addEventListener('scroll', scrollDebounceFnRef.current, false) + } + return () => { + if (qrRoot && scrollDebounceFnRef.current) { + qrRoot.removeEventListener('scroll', scrollDebounceFnRef.current, false) + } + if (scrollDebounceFnRef.current && scrollDebounceFnRef.current.cancel) { + scrollDebounceFnRef.current.cancel() + } + } + }, [onScroll]) - componentWillUnmount() { - document - .getElementById('qr-root') - .removeEventListener('scroll', this.scrollDebounceFn(), false) - } + const filterSegments = useCallback((filterValue) => { + setFilter(filterValue) + QualityReportActions.filterSegments(filterValue, null) + }, []) - render() { - let totalSegments = 0 - if (this.props.segmentsFiles) { - this.props.segmentsFiles.forEach((ss) => (totalSegments += ss.size)) - } + let totalSegments = 0 + if (props.segmentsFiles) { + props.segmentsFiles.forEach((ss) => (totalSegments += ss.size)) + } - return ( -
    -
    -
    -

    Segment details

    - -
    - {this.props.files && this.props.files.length === 0 ? ( -
    No segments found
    - ) : ( - this.getFiles() - )} + return ( +
    +
    +
    +
    Segment details
    + +
    + {props.files && props.files.length === 0 ? ( +
    No segments found
    + ) : ( + getFiles() + )} - {this.props.moreSegments && - this.props.files && - this.props.files.size !== 0 && - totalSegments >= 20 ? ( -
    -
    -
    -
    - Loading more segments -
    -
    -
    + {props.moreSegments && + props.files && + props.files.size !== 0 && + totalSegments >= 20 ? ( +
    +
    +
    - ) : null} -
    +
    + ) : null}
    - ) - } +
    + ) } export default SegmentsDetails diff --git a/public/js/components/review/QualityReportButton.js b/public/js/components/review/QualityReportButton.js index 68aafc42c5..67b18adbaa 100644 --- a/public/js/components/review/QualityReportButton.js +++ b/public/js/components/review/QualityReportButton.js @@ -1,13 +1,22 @@ import React, {useEffect, useState, useRef} from 'react' -import classnames from 'classnames' -import {IconQR} from '../icons/IconQR' import CatToolStore from '../../stores/CatToolStore' import CattoolConstants from '../../constants/CatToolConstants' import CatToolActions from '../../actions/CatToolActions' import {reloadQualityReport} from '../../api/reloadQualityReport' import CommonUtils from '../../utils/commonUtils' import {REVISE_STEP_NUMBER} from '../../constants/Constants' +import QualityReportIcon from '../../../img/icons/QualityReportIcon' +import { + DROPDOWN_MENU_TRIGGER_MODE, + DropdownMenu, +} from '../common/DropdownMenu/DropdownMenu' +import { + Button, + BUTTON_MODE, + BUTTON_SIZE, + BUTTON_TYPE, +} from '../common/Button/Button' /** * @NOTE because the state of this component is manipulated @@ -19,22 +28,18 @@ export const QualityReportButton = ({ revisionNumber, secondRevisionsCount, qualityReportHref, - overallQualityClass, }) => { const [is_pass, setIsPass] = useState() - // const [score, setScore] = useState() - const [vote, setVote] = useState() const [progress, setProgress] = useState() const [feedback, setFeedback] = useState() + const [revisionStarted, setRevisionStarted] = useState(false) const revision_number = revisionNumber ? revisionNumber : '1' const qrParam = secondRevisionsCount ? '?revision_type=' + revision_number : '' const quality_report_href = useRef(qualityReportHref + qrParam) - const openFeedbackModal = (e) => { - e.preventDefault() - e.stopPropagation() + const openFeedbackModal = () => { CatToolActions.openFeedbackModal(feedback, revisionNumber) } @@ -44,15 +49,12 @@ export const QualityReportButton = ({ const review = qr.chunk.reviews.find(function (value) { return value.revision_number === revNumber }) - let newVote = '' if (review) { - if (review.is_pass != null && isReview) { - newVote = review.is_pass ? 'excellent' : 'fail' - } setIsPass(review.is_pass) - setVote(newVote) - // setScore(review.score) setFeedback(review.feedback) + setRevisionStarted(true) + } else { + setRevisionStarted(false) } CatToolActions.updateQualityReport(qr) } @@ -99,57 +101,68 @@ export const QualityReportButton = ({ } }, []) - return ( -
    -
    { + return progress && + isReview && + (revisionNumber === 1 || revisionNumber === 2) ? ( + + + {!feedback && progress && ( +
    + )} + + ), + size: BUTTON_SIZE.ICON_STANDARD, + mode: + is_pass || revisionStarted + ? BUTTON_MODE.OUTLINE_BG + : BUTTON_MODE.GHOST, + type: is_pass + ? BUTTON_TYPE.SUCCESS + : revisionStarted + ? BUTTON_TYPE.CRITICAL + : BUTTON_TYPE.ICON, + onClick: () => { window.open(quality_report_href.current, '_blank') - }} - > - - - {isReview && !feedback && progress && ( - + }, + }} + items={[ + { + label: 'Open QR', + onClick: (e) => { + e.stopPropagation() + window.open(quality_report_href.current, '_blank') + }, + }, + { + label: !feedback + ? `Write feedback (R${revisionNumber})` + : `Edit feedback (R${revisionNumber})`, + onClick: openFeedbackModal, + }, + ]} + /> + ) : ( + ) } diff --git a/public/js/components/review_extended/ReviewExtendedCategorySelector.js b/public/js/components/review_extended/ReviewExtendedCategorySelector.js index 2af2e627c8..b90dd201e4 100644 --- a/public/js/components/review_extended/ReviewExtendedCategorySelector.js +++ b/public/js/components/review_extended/ReviewExtendedCategorySelector.js @@ -36,7 +36,7 @@ const ReviewExtendedCategorySelector = ({ align={DROPDOWN_MENU_ALIGN.RIGHT} toggleButtonProps={{ mode: BUTTON_MODE.OUTLINE, - size: BUTTON_SIZE.ICON_SMALL, + size: BUTTON_SIZE.ICON_XSMALL, className: 'severities-dropdown-trigger', children: , }} diff --git a/public/js/components/review_extended/ReviewExtendedIssue.js b/public/js/components/review_extended/ReviewExtendedIssue.js index 89e60cfb35..8e8af0d29b 100644 --- a/public/js/components/review_extended/ReviewExtendedIssue.js +++ b/public/js/components/review_extended/ReviewExtendedIssue.js @@ -12,6 +12,9 @@ import IconEdit from '../icons/IconEdit' import ReviewExtendedIssuePanel from './ReviewExtendedIssuePanel' import Trash from '../../../img/icons/Trash' import {ApplicationWrapperContext} from '../common/ApplicationWrapper/ApplicationWrapperContext' +import {Button, BUTTON_MODE} from '../common/Button/Button' +import CommentsSquareIconFilled from '../../../img/icons/CommentsSquareIconFilled' +import CommentsSquareIcon from '../../../img/icons/CommentsSquareIcon' export const ReviewExtendedIssue = ({ sid, @@ -242,15 +245,6 @@ export const ReviewExtendedIssue = ({ const category = getCategory() const severity = getSeverity() - let commentViewButtonClass = commentView ? 're-active' : '' - commentViewButtonClass = - issue.comments.length > 0 || issue.target_text - ? +' re-message' - : commentViewButtonClass - let iconCommentClass = - issue.comments.length > 0 || issue.target_text - ? 'icon-uniE96B icon' - : 'icon-uniE96E icon' //START comments html section let htmlCommentLines = generateHtmlCommentLines() @@ -317,34 +311,36 @@ export const ReviewExtendedIssue = ({
    {actions && (
    - + {issue.comments.length > 0 || issue.target_text ? ( + + ) : ( + + )} + {isReview && issue.revision_number <= currentReview && isUserAuthorizedToEditIssue && ( <> - - + + )}
    diff --git a/public/js/components/segments/SegmentButtons.js b/public/js/components/segments/SegmentButtons.js index 4ed397b1af..8fcecded1e 100644 --- a/public/js/components/segments/SegmentButtons.js +++ b/public/js/components/segments/SegmentButtons.js @@ -8,7 +8,7 @@ import SegmentFilter from '../header/cattol/segment_filter/segment_filter' import SegmentUtils from '../../utils/segmentUtils' import CattoolConstants from '../../constants/CatToolConstants' import CommonUtils from '../../utils/commonUtils' -import {SEGMENTS_STATUS} from '../../constants/Constants' +import {REVISE_STEP_NUMBER, SEGMENTS_STATUS} from '../../constants/Constants' import { decodePlaceholdersToPlainText, removeTagsFromText, @@ -18,6 +18,7 @@ import UserStore from '../../stores/UserStore' import {isMacOS} from '../../utils/Utils' import {useHotkeys} from 'react-hotkeys-hook' import {Shortcuts} from '../../utils/shortcuts' +import {Button, BUTTON_SIZE, BUTTON_TYPE} from '../common/Button/Button' export const SegmentButton = ({segment, disabled, isReview}) => { useHotkeys( @@ -141,7 +142,6 @@ export const SegmentButton = ({segment, disabled, isReview}) => { } const getReviewButtons = () => { - const classDisable = disabled ? 'disabled' : '' let nextButton, currentButton let nextSegment = SegmentStore.getNextSegment({ current_sid: segment.sid, @@ -167,9 +167,14 @@ export const SegmentButton = ({segment, disabled, isReview}) => { nextSegment.status === 'NEW' || nextSegment.status === 'DRAFT') const filtering = SegmentFilter.enabled() && SegmentFilter.filtering() - const className = config.isReview - ? 'revise-button-' + config.revisionNumber - : '' + const type = + config.revisionNumber === REVISE_STEP_NUMBER.REVISE1 + ? BUTTON_TYPE.SUCCESS + : BUTTON_TYPE.PURPLE + const status = + config.revisionNumber === REVISE_STEP_NUMBER.REVISE1 + ? SEGMENTS_STATUS.APPROVED + : SEGMENTS_STATUS.APPROVED2 enableGoToNext = enableGoToNext && (isNull(nextSegment.revision_number) || @@ -180,78 +185,63 @@ export const SegmentButton = ({segment, disabled, isReview}) => { (SegmentUtils.isIceSegment(nextSegment) && !nextSegment.unlocked)) // Ice Locked nextButton = enableGoToNext ? ( -
  • - clickOnApprovedButton(event, true)} - className={'btn next-unapproved ' + classDisable + ' ' + className} - data-segmentid={'segment-' + segment.sid} - title="Revise and go to next translated" - > - {' '} - A+>> - -

    - {isMac ? 'CMD' : 'CTRL'} - +SHIFT+ENTER -

    -
  • + ) : null currentButton = getReviewButton() if (filtering) { nextButton = null - var data = SegmentFilter.getStoredState() - var filterinRepetitions = + const data = SegmentFilter.getStoredState() + const filterinRepetitions = data.reactState && data.reactState.samplingType === 'repetitions' if (filterinRepetitions) { - nextButton = ( - -
  • - goToNextRepetition(e, 'approved')} - className={ - 'next-review-repetition ui green button ' + className - } - data-segmentid={'segment-' + segment.sid} - title="Revise and go to next repetition" - > - REP < - -
  • -
  • - goToNextRepetitionGroup(e, 'approved')} - className={ - 'next-review-repetition-group ui green button ' + className - } - data-segmentid={'segment-' + segment.sid} - title="Revise and go to next repetition group" - > - REP << - -
  • -
    + nextButton = [] + nextButton.push( + , + ) + nextButton.push( + , ) } } return ( -
      {nextButton} {currentButton} -
    +
    ) } const getTranslateButtons = () => { - const classDisable = disabled ? 'disabled' : '' - let nextButton, currentButton const filtering = SegmentFilter.enabled() && SegmentFilter.filtering() && SegmentFilter.open @@ -272,127 +262,100 @@ export const SegmentButton = ({segment, disabled, isReview}) => { if (currentSegmentTPEnabled) { nextButton = '' currentButton = ( -
  • - clickOnGuessTags(e)} - data-segmentid={'segment-' + segment.sid} - className={'guesstags ' + classDisable} - > - {' '} - GUESS TAGS - -

    - {isMac ? 'CMD' : 'CTRL'} - ENTER -

    -
  • + ) } else { nextButton = enableGoToNext ? ( -
  • - clickOnTranslatedButton(e, true)} - className={'btn next-untranslated ' + classDisable} - data-segmentid={'segment-' + segment.sid} - title="Translate and go to next untranslated" - > - {' '} - T+>> - -

    - {isMac ? 'CMD' : 'CTRL'} - +SHIFT+ENTER -

    -
  • + ) : null currentButton = getTranslateButton() } if (filtering) { nextButton = null - var data = SegmentFilter.getStoredState() - var filterinRepetitions = + const data = SegmentFilter.getStoredState() + const filterinRepetitions = data.reactState && data.reactState.samplingType === 'repetitions' if (filterinRepetitions) { - nextButton = ( - -
  • - goToNextRepetition(e, 'translated')} - className="next-repetition ui primary button" - data-segmentid={'segment-' + segment.sid} - title="Translate and go to next repetition" - > - REP > - -
  • -
  • - goToNextRepetitionGroup(e, 'translated')} - className="next-repetition-group ui primary button" - data-segmentid={'segment-' + segment.sid} - title="Translate and go to next repetition group" - > - REP >> - -
  • -
    + nextButton = [] + nextButton.push( + , + ) + nextButton.push( + , ) } } return ( -
      {nextButton} {currentButton} -
    +
    ) } const getTranslateButton = () => { - const classDisable = disabled ? 'disabled' : '' return ( -
  • - clickOnTranslatedButton(e, false)} - data-segmentid={'segment-' + segment.sid} - className={'translated ' + classDisable} - > - {' '} - {config.status_labels.TRANSLATED}{' '} - -

    {isMac ? 'CMD' : 'CTRL'}+ENTER

    -
  • + ) } const getReviewButton = () => { - const classDisable = disabled ? 'disabled' : '' - const className = config.isReview - ? 'revise-button-' + config.revisionNumber - : '' - + const type = + config.revisionNumber === REVISE_STEP_NUMBER.REVISE1 + ? BUTTON_TYPE.SUCCESS + : BUTTON_TYPE.PURPLE return ( -
  • - clickOnApprovedButton(event, false)} - className={'approved ' + classDisable + ' ' + className} - > - {' '} - {config.status_labels.APPROVED}{' '} - -

    {isMac ? 'CMD' : 'CTRL'}+ENTER

    -
  • + ) } diff --git a/public/js/components/segments/SegmentCommentsContainer.js b/public/js/components/segments/SegmentCommentsContainer.js index 17016160eb..2c99e2a94e 100644 --- a/public/js/components/segments/SegmentCommentsContainer.js +++ b/public/js/components/segments/SegmentCommentsContainer.js @@ -94,7 +94,10 @@ class SegmentCommentsContainer extends React.Component { } resolveThread() { - CommentsActions.resolveThread(this.context.segment.original_sid, this.state.anonymousComments) + CommentsActions.resolveThread( + this.context.segment.original_sid, + this.state.anonymousComments, + ) } updateComments(sid) { @@ -213,11 +216,14 @@ class SegmentCommentsContainer extends React.Component {
    {comment.is_anonymous === 0 && ( - - {comment.full_name} - + + {comment.full_name} + )} - {comment.is_anonymous === 0 ? "m" : "M"}arked as resolved + + {' '} + {comment.is_anonymous === 0 ? 'm' : 'M'}arked as resolved +
    , ) @@ -239,7 +245,7 @@ class SegmentCommentsContainer extends React.Component {
    - + + Add Term +
    ) diff --git a/public/js/components/segments/SegmentFooterTabGlossary/TermForm.js b/public/js/components/segments/SegmentFooterTabGlossary/TermForm.js index e3af2eabec..90aeca6caa 100644 --- a/public/js/components/segments/SegmentFooterTabGlossary/TermForm.js +++ b/public/js/components/segments/SegmentFooterTabGlossary/TermForm.js @@ -6,6 +6,12 @@ import CatToolActions from '../../../actions/CatToolActions' import {KeysSelect} from './KeysSelect' import {DomainSelect} from './DomainSelect' import {SubdomainSelect} from './SubdomainSelect' +import { + Button, + BUTTON_MODE, + BUTTON_SIZE, + BUTTON_TYPE, +} from '../../common/Button/Button' const TermForm = () => { const { @@ -292,21 +298,25 @@ const TermForm = () => { {showMore ? 'Hide options' : 'More options'}
    - - +
    diff --git a/public/js/components/segments/SegmentFooterTabIcu.js b/public/js/components/segments/SegmentFooterTabIcu.js index fee1ba157d..1949d94939 100644 --- a/public/js/components/segments/SegmentFooterTabIcu.js +++ b/public/js/components/segments/SegmentFooterTabIcu.js @@ -175,16 +175,6 @@ const SegmentFooterTabIcu = ({segment, active_class, tab_class}) => { formatMessage.setup({ locale: config.target_code.split('-')[0], }) - console.log( - 'message', - formatMessage( - textUtils.removeWhitespacePlaceholders( - transformTagsToText(removeTagsFromText(segment.translation)), - ), - valuesNew, - ), - valuesNew, - ) return formatMessage( textUtils.removeWhitespacePlaceholders( transformTagsToText(removeTagsFromText(segment.translation)), diff --git a/public/js/components/segments/SegmentFooterTabIcu.test.js b/public/js/components/segments/SegmentFooterTabIcu.test.js index 7cfc9c50a2..cb61e4e5f2 100644 --- a/public/js/components/segments/SegmentFooterTabIcu.test.js +++ b/public/js/components/segments/SegmentFooterTabIcu.test.js @@ -9,6 +9,18 @@ window.config = { isTargetRTL: false, } +// Suppress expected console output from format-message and ICU parser during tests +beforeEach(() => { + jest.spyOn(console, 'warn').mockImplementation(() => {}) + jest.spyOn(console, 'error').mockImplementation(() => {}) + jest.spyOn(console, 'log').mockImplementation(() => {}) +}) +afterEach(() => { + console.warn.mockRestore() + console.error.mockRestore() + console.log.mockRestore() +}) + const createSegment = (translation) => ({ segment: translation, translation, diff --git a/public/js/components/segments/SegmentTarget.js b/public/js/components/segments/SegmentTarget.js index 62ab519c5b..51f8e46515 100644 --- a/public/js/components/segments/SegmentTarget.js +++ b/public/js/components/segments/SegmentTarget.js @@ -16,18 +16,10 @@ import { textHasTags, } from './utils/DraftMatecatUtils/tagUtils' import {Button, BUTTON_MODE, BUTTON_SIZE} from '../common/Button/Button' -import RemoveTagsIcon from '../../../img/icons/RemoveTagsIcon' -import AddTagsIcon from '../../../img/icons/AddTagsIcon' -import UpperCaseIcon from '../../../img/icons/UpperCaseIcon' -import LowerCaseIcon from '../../../img/icons/LowerCaseIcon' -import CapitalizeIcon from '../../../img/icons/CapitalizeIcon' -import QualityReportIcon from '../../../img/icons/QualityReportIcon' import ReviseLockIcon from '../../../img/icons/ReviseLockIcon' import OfflineUtils from '../../utils/offlineUtils' import SegmentUtils from '../../utils/segmentUtils' import CatToolStore from '../../stores/CatToolStore' -import {Shortcuts} from '../../utils/shortcuts' -import {UseHotKeysComponent} from '../../hooks/UseHotKeysComponent' import {SegmentTargetToolbar} from './SegmentTargetToolbar' class SegmentTarget extends React.Component { @@ -112,6 +104,11 @@ class SegmentTarget extends React.Component { const {showFormatMenu} = this.state const {toggleFormatMenu, updateCounter} = this + const buttonsDisabled = + !translation || + translation.trim().length === 0 || + OfflineUtils.offlineCacheRemaining <= 0 + var textAreaContainer = '' let issues = this.getAllIssues() if (this.props.segment.edit_area_locked) { @@ -141,25 +138,26 @@ class SegmentTarget extends React.Component { )} />
    -
    - {config.isReview ? ( - - ) : null} +
    +
    + {config.isReview ? ( + + ) : null} +
    +
    ) } else { - let tagCopyButton, - removeTagsButton, - s2tMicro = '' + let s2tMicro = '' //Speeche2Text var s2t_enabled = this.context.speech2textEnabledFn() @@ -192,57 +190,6 @@ class SegmentTarget extends React.Component {
    ) } - if (textHasTags(translation)) { - removeTagsButton = ( - <> - - - - ) - } - if ( - segment.missingTagsInTarget && - segment.missingTagsInTarget.length > 0 && - this.editArea - ) { - tagCopyButton = ( - <> - - - - ) - } const qrLink = '/revise-summary/' + @@ -265,22 +212,25 @@ class SegmentTarget extends React.Component { updateCounter={updateCounter} /> {s2tMicro} - +
    + + +
    ) } @@ -353,17 +303,8 @@ class SegmentTarget extends React.Component { } render() { - let buttonsDisabled = false let translation = this.props.segment.translation - if ( - !translation || - translation.trim().length === 0 || - OfflineUtils.offlineCacheRemaining <= 0 - ) { - buttonsDisabled = true - } - return (
    - {this.props.segment.warnings ? ( ) : null} diff --git a/public/js/components/segments/SegmentTargetToolbar.js b/public/js/components/segments/SegmentTargetToolbar.js index 13f996a93b..51380990b9 100644 --- a/public/js/components/segments/SegmentTargetToolbar.js +++ b/public/js/components/segments/SegmentTargetToolbar.js @@ -1,4 +1,4 @@ -import React, {useState} from 'react' +import React, {useEffect, useRef, useState} from 'react' import PropTypes from 'prop-types' import {Button, BUTTON_MODE, BUTTON_SIZE} from '../common/Button/Button' import ReviseLockIcon from '../../../img/icons/ReviseLockIcon' @@ -18,6 +18,8 @@ import {UseHotKeysComponent} from '../../hooks/UseHotKeysComponent' import AddTagsIcon from '../../../img/icons/AddTagsIcon' import {AiAlternatives} from './ToolbarFeatures/Ai/AiAlternatives' import {AiFeedback} from './ToolbarFeatures/Ai/AiFeedback' +import Star from '../icons/Star' +import useResizeObserver from '../../hooks/useResizeObserver' export const SegmentTargetToolbar = ({ sid, @@ -34,12 +36,19 @@ export const SegmentTargetToolbar = ({ }) => { const [isIconsBundled, setIsIconsBundled] = useState(false) + const ref = useRef() + + const {width} = useResizeObserver({current: ref?.current?.parentNode}) + + useEffect(() => { + setIsIconsBundled(width <= 400) + }, [width]) + const getIconButton = (props) => { const {children, ...rest} = props return ( ) ) } + +AiAlternatives.propTypes = { + sid: PropTypes.string.isRequired, + editArea: PropTypes.object.isRequired, + isIconsBundled: PropTypes.bool, +} diff --git a/public/js/components/segments/ToolbarFeatures/Ai/AiFeedback.js b/public/js/components/segments/ToolbarFeatures/Ai/AiFeedback.js index 2cdbf81ee5..4146cc2c33 100644 --- a/public/js/components/segments/ToolbarFeatures/Ai/AiFeedback.js +++ b/public/js/components/segments/ToolbarFeatures/Ai/AiFeedback.js @@ -1,11 +1,12 @@ import React, {useContext} from 'react' +import PropTypes from 'prop-types' import {Button, BUTTON_MODE, BUTTON_SIZE} from '../../../common/Button/Button' import SegmentActions from '../../../../actions/SegmentActions' import {ApplicationWrapperContext} from '../../../common/ApplicationWrapper/ApplicationWrapperContext' import CommonUtils from '../../../../utils/commonUtils' import Feedback from '../../../icons/Feedback' -export const AiFeedback = ({sid, segment}) => { +export const AiFeedback = ({sid, segment, isIconsBundled}) => { const {userInfo} = useContext(ApplicationWrapperContext) const openTab = () => { @@ -19,7 +20,7 @@ export const AiFeedback = ({sid, segment}) => { jobId: config.id_job, segmentId: sid, } - CommonUtils.dispatchTrackingEvents('AiFeedback', message) + CommonUtils.dispatchTrackingEvents('LaraStyle', message) } const isDisabled = @@ -29,9 +30,9 @@ export const AiFeedback = ({sid, segment}) => { return ( !config.isReview && ( ) ) } + +AiFeedback.propTypes = { + sid: PropTypes.string.isRequired, + isIconsBundled: PropTypes.bool, +} diff --git a/public/js/components/segments/ToolbarFeatures/Ai/LaraStyles.js b/public/js/components/segments/ToolbarFeatures/Ai/LaraStyles.js index 3d887efaa4..182f9854af 100644 --- a/public/js/components/segments/ToolbarFeatures/Ai/LaraStyles.js +++ b/public/js/components/segments/ToolbarFeatures/Ai/LaraStyles.js @@ -6,8 +6,9 @@ import SegmentActions from '../../../../actions/SegmentActions' import {ApplicationWrapperContext} from '../../../common/ApplicationWrapper/ApplicationWrapperContext' import CatToolStore from '../../../../stores/CatToolStore' import CommonUtils from '../../../../utils/commonUtils' +import PropTypes from 'prop-types' -export const LaraStyles = ({sid, segment}) => { +export const LaraStyles = ({sid, segment, isIconsBundled}) => { const {userInfo} = useContext(ApplicationWrapperContext) const contributions = segment?.contributions @@ -45,9 +46,9 @@ export const LaraStyles = ({sid, segment}) => { return ( !config.isReview && ( ) ) } + +LaraStyles.propTypes = { + sid: PropTypes.string.isRequired, + isIconsBundled: PropTypes.bool, +} diff --git a/public/js/components/settingsPanel/Contents/AnalysisTab/LanguagesExceptions.js b/public/js/components/settingsPanel/Contents/AnalysisTab/LanguagesExceptions.js index 2c1fc14d53..3edb08db5e 100644 --- a/public/js/components/settingsPanel/Contents/AnalysisTab/LanguagesExceptions.js +++ b/public/js/components/settingsPanel/Contents/AnalysisTab/LanguagesExceptions.js @@ -12,7 +12,6 @@ import { BUTTON_SIZE, BUTTON_TYPE, } from '../../../common/Button/Button' -import AddWide from '../../../../../img/icons/AddWide' import {CreateProjectContext} from '../../../createProject/CreateProjectContext' import {Select} from '../../../common/Select' import {InputPercentage} from './InputPercentage' @@ -177,7 +176,6 @@ export const LanguagesExceptions = ({breakdowns, updateExceptions}) => {

    diff --git a/public/js/components/settingsPanel/Contents/MachineTranslationTab/DeepLGlossary/DeepLGlossary.js b/public/js/components/settingsPanel/Contents/MachineTranslationTab/DeepLGlossary/DeepLGlossary.js index 37caa010a8..6ec2964712 100644 --- a/public/js/components/settingsPanel/Contents/MachineTranslationTab/DeepLGlossary/DeepLGlossary.js +++ b/public/js/components/settingsPanel/Contents/MachineTranslationTab/DeepLGlossary/DeepLGlossary.js @@ -17,6 +17,7 @@ import ModalsActions from '../../../../../actions/ModalsActions' import {ConfirmDeleteResourceProjectTemplates} from '../../../../modals/ConfirmDeleteResourceProjectTemplates' import {SCHEMA_KEYS} from '../../../../../hooks/useProjectTemplates' import {DeepLGlossaryNoneRow} from './DeepLGlossaryNoneRow' +import {Button, BUTTON_TYPE} from '../../../../common/Button/Button' const COLUMNS_TABLE = [ {name: 'Active'}, @@ -311,44 +312,49 @@ export const DeepLGlossary = ({id, setGlossaries, isCattoolPage = false}) => { ) return ( -

    - {haveRecords && ( - + <> + {(!isCattoolPage || (isCattoolPage && haveRecords)) && ( +

    Glossaries

    )} +
    + {haveRecords && ( + + )} - {!isCattoolPage && - (haveRecords ? ( -
    - {!shouldHideNewButton && ( - + )} +
    + ) : Array.isArray(rows) ? ( +
    +

    Start using DeepL's glossary feature

    + - )} -
    - ) : Array.isArray(rows) ? ( -
    -

    Start using DeepL's glossary feature

    - -
    - ) : ( -

    Loading...

    - ))} -
    + +
    + ) : ( +

    Loading...

    + ))} +
    + ) } diff --git a/public/js/components/settingsPanel/Contents/MachineTranslationTab/DeepLGlossary/DeepLGlossaryCreateRow.js b/public/js/components/settingsPanel/Contents/MachineTranslationTab/DeepLGlossary/DeepLGlossaryCreateRow.js index 71d28ce1ef..de97f8890d 100644 --- a/public/js/components/settingsPanel/Contents/MachineTranslationTab/DeepLGlossary/DeepLGlossaryCreateRow.js +++ b/public/js/components/settingsPanel/Contents/MachineTranslationTab/DeepLGlossary/DeepLGlossaryCreateRow.js @@ -8,6 +8,12 @@ import {createAndImportDeepLGlossary} from '../../../../../api/createAndImportDe import LabelWithTooltip from '../../../../common/LabelWithTooltip' import CatToolActions from '../../../../../actions/CatToolActions' import {SettingsPanelContext} from '../../../SettingsPanelContext' +import { + Button, + BUTTON_HTML_TYPE, + BUTTON_SIZE, + BUTTON_TYPE, +} from '../../../../common/Button/Button' export const DeepLGlossaryCreateRow = ({engineId, row, setRows}) => { const {portalTarget} = useContext(SettingsPanelContext) @@ -172,25 +178,27 @@ export const DeepLGlossaryCreateRow = ({engineId, row, setRows}) => { isWaitingResult ? ' row-content-create-glossary-waiting' : '' }`} > - +
    - +
    {isWaitingResult &&
    } diff --git a/public/js/components/settingsPanel/Contents/MachineTranslationTab/DeepLGlossary/DeepLGlossaryRow.js b/public/js/components/settingsPanel/Contents/MachineTranslationTab/DeepLGlossary/DeepLGlossaryRow.js index 08d0ff6781..5d1acacea9 100644 --- a/public/js/components/settingsPanel/Contents/MachineTranslationTab/DeepLGlossary/DeepLGlossaryRow.js +++ b/public/js/components/settingsPanel/Contents/MachineTranslationTab/DeepLGlossary/DeepLGlossaryRow.js @@ -1,6 +1,11 @@ import React, {Fragment, useEffect, useState} from 'react' import PropTypes from 'prop-types' import Trash from '../../../../../../img/icons/Trash' +import { + Button, + BUTTON_SIZE, + BUTTON_TYPE, +} from '../../../../common/Button/Button' export const DeepLGlossaryRow = ({ engineId, @@ -49,14 +54,16 @@ export const DeepLGlossaryRow = ({ <>
    - +
    {isWaitingResult &&
    } diff --git a/public/js/components/settingsPanel/Contents/MachineTranslationTab/DeepLOptions/DeepLOptions.js b/public/js/components/settingsPanel/Contents/MachineTranslationTab/DeepLOptions/DeepLOptions.js index 9231802495..e01b0615ef 100644 --- a/public/js/components/settingsPanel/Contents/MachineTranslationTab/DeepLOptions/DeepLOptions.js +++ b/public/js/components/settingsPanel/Contents/MachineTranslationTab/DeepLOptions/DeepLOptions.js @@ -104,7 +104,6 @@ export const DeepLOptions = ({isCattoolPage}) => { )} />
    -

    Glossaries

    { const onClickConfirm = () => { @@ -23,20 +24,22 @@ export const DeleteResource = ({row, onClose, onConfirm, type = 'mt'}) => {
    - + - +
    diff --git a/public/js/components/settingsPanel/Contents/MachineTranslationTab/LaraGlossary/LaraGlossary.js b/public/js/components/settingsPanel/Contents/MachineTranslationTab/LaraGlossary/LaraGlossary.js index b973f355a3..da3b36527b 100644 --- a/public/js/components/settingsPanel/Contents/MachineTranslationTab/LaraGlossary/LaraGlossary.js +++ b/public/js/components/settingsPanel/Contents/MachineTranslationTab/LaraGlossary/LaraGlossary.js @@ -1,4 +1,10 @@ -import React, {useCallback, useContext, useEffect, useRef, useState} from 'react' +import React, { + useCallback, + useContext, + useEffect, + useRef, + useState, +} from 'react' import PropTypes from 'prop-types' import {SettingsPanelTable} from '../../../SettingsPanelTable' import {SettingsPanelContext} from '../../../SettingsPanelContext' @@ -8,6 +14,7 @@ import {getLaraGlossaries} from '../../../../../api/getLaraGlossaries/getLaraGlo import CatToolStore from '../../../../../stores/CatToolStore' import CatToolConstants from '../../../../../constants/CatToolConstants' import CatToolActions from '../../../../../actions/CatToolActions' +import {Button, BUTTON_TYPE} from '../../../../common/Button/Button' const COLUMNS_TABLE = [ {name: 'Active'}, @@ -60,7 +67,7 @@ export const LaraGlossary = ({id, setGlossaries, isCattoolPage = false}) => { const getJobMetadata = ({jobMetadata: {project} = {}}) => { const rows = memories.filter(({id}) => { const laraGlossaries = project.mt_extra?.lara_glossaries - ? project.mt_extra.lara_glossaries + ? project.mt_extra.lara_glossaries : [] return laraGlossaries.some((value) => value === id) @@ -147,40 +154,42 @@ export const LaraGlossary = ({id, setGlossaries, isCattoolPage = false}) => { const haveRecords = rows?.length > 0 return ( -
    - {haveRecords && ( - + <> + {(!isCattoolPage || (isCattoolPage && haveRecords)) && ( +

    Glossaries

    )} - - {!isCattoolPage && - (haveRecords ? ( -
    - -
    - ) : Array.isArray(rows) ? ( -
    -

    Start using Lara's glossary feature

    - -
    - ) : ( -

    Loading...

    - ))} -
    +
    + {haveRecords && ( + + )} + + {!isCattoolPage && + (haveRecords ? ( +
    + +
    + ) : Array.isArray(rows) ? ( +
    +

    Start using Lara's glossary feature

    + +
    + ) : ( +

    Loading...

    + ))} +
    + ) } diff --git a/public/js/components/settingsPanel/Contents/MachineTranslationTab/LaraOptions/LaraOptions.js b/public/js/components/settingsPanel/Contents/MachineTranslationTab/LaraOptions/LaraOptions.js index bfe12c9013..6156501bbf 100644 --- a/public/js/components/settingsPanel/Contents/MachineTranslationTab/LaraOptions/LaraOptions.js +++ b/public/js/components/settingsPanel/Contents/MachineTranslationTab/LaraOptions/LaraOptions.js @@ -129,7 +129,6 @@ export const LaraOptions = ({isCattoolPage}) => { )} />
    -

    Glossaries

    { (haveRecords ? (
    {!shouldHideNewButton && ( - + )}
    ) : Array.isArray(rows) ? (

    Start using ModernMT’s glossary feature

    - +
    ) : (

    Loading...

    diff --git a/public/js/components/settingsPanel/Contents/MachineTranslationTab/MTGlossary/MTGlossaryCreateRow.js b/public/js/components/settingsPanel/Contents/MachineTranslationTab/MTGlossary/MTGlossaryCreateRow.js index f849e6c1fc..6761335990 100644 --- a/public/js/components/settingsPanel/Contents/MachineTranslationTab/MTGlossary/MTGlossaryCreateRow.js +++ b/public/js/components/settingsPanel/Contents/MachineTranslationTab/MTGlossary/MTGlossaryCreateRow.js @@ -8,6 +8,12 @@ import {createMemoryAndImportGlossary} from '../../../../../api/createMemoryAndI import LabelWithTooltip from '../../../../common/LabelWithTooltip' import CatToolActions from '../../../../../actions/CatToolActions' import {SettingsPanelContext} from '../../../SettingsPanelContext' +import { + Button, + BUTTON_HTML_TYPE, + BUTTON_SIZE, + BUTTON_TYPE, +} from '../../../../common/Button/Button' export const MTGlossaryCreateRow = ({engineId, row, setRows}) => { const {portalTarget} = useContext(SettingsPanelContext) @@ -191,25 +197,27 @@ export const MTGlossaryCreateRow = ({engineId, row, setRows}) => { isWaitingResult ? ' row-content-create-glossary-waiting' : '' }`} > - +
    - +
    {isWaitingResult &&
    } diff --git a/public/js/components/settingsPanel/Contents/MachineTranslationTab/MTGlossary/MTGlossaryRow.js b/public/js/components/settingsPanel/Contents/MachineTranslationTab/MTGlossary/MTGlossaryRow.js index 73f3d9c167..976583c8d8 100644 --- a/public/js/components/settingsPanel/Contents/MachineTranslationTab/MTGlossary/MTGlossaryRow.js +++ b/public/js/components/settingsPanel/Contents/MachineTranslationTab/MTGlossary/MTGlossaryRow.js @@ -18,6 +18,11 @@ import Close from '../../../../../../img/icons/Close' import LabelWithTooltip from '../../../../common/LabelWithTooltip' import CatToolActions from '../../../../../actions/CatToolActions' import {SettingsPanelContext} from '../../../SettingsPanelContext' +import { + Button, + BUTTON_SIZE, + BUTTON_TYPE, +} from '../../../../common/Button/Button' export const MTGlossaryRow = ({ engineId, @@ -138,28 +143,36 @@ export const MTGlossaryRow = ({ } const editingNameButtons = !isEditingName ? ( - + ) : (
    - - +
    ) @@ -217,14 +230,16 @@ export const MTGlossaryRow = ({
    - +
    {isWaitingResult &&
    } diff --git a/public/js/components/settingsPanel/Contents/MachineTranslationTab/MTRow.js b/public/js/components/settingsPanel/Contents/MachineTranslationTab/MTRow.js index 5be6d34077..c902a92035 100644 --- a/public/js/components/settingsPanel/Contents/MachineTranslationTab/MTRow.js +++ b/public/js/components/settingsPanel/Contents/MachineTranslationTab/MTRow.js @@ -2,6 +2,8 @@ import React, {useContext} from 'react' import PropTypes from 'prop-types' import {SettingsPanelContext} from '../../SettingsPanelContext' import InfoIcon from '../../../../../img/icons/InfoIcon' +import {Button, BUTTON_SIZE} from '../../../common/Button/Button' +import Trash from '../../../../../img/icons/Trash' export const MTRow = ({row, deleteMT, onCheckboxClick}) => { const {currentProjectTemplate} = useContext(SettingsPanelContext) @@ -28,7 +30,7 @@ export const MTRow = ({row, deleteMT, onCheckboxClick}) => { target="_blank" rel="noreferrer" > - + )} {row.engine_type === 'MMT' && ( @@ -37,7 +39,7 @@ export const MTRow = ({row, deleteMT, onCheckboxClick}) => { target="_blank" rel="noreferrer" > - + )} {row.engine_type === 'DeepL' && ( @@ -46,7 +48,7 @@ export const MTRow = ({row, deleteMT, onCheckboxClick}) => { target="_blank" rel="noreferrer" > - + )} {row.engine_type === 'Lara' && ( @@ -55,7 +57,7 @@ export const MTRow = ({row, deleteMT, onCheckboxClick}) => { target="_blank" rel="noreferrer" > - + )} {row.engine_type === 'Intento' && ( @@ -64,7 +66,7 @@ export const MTRow = ({row, deleteMT, onCheckboxClick}) => { target="_blank" rel="noreferrer" > - + )}
    @@ -80,13 +82,14 @@ export const MTRow = ({row, deleteMT, onCheckboxClick}) => { >
    {!row.default && !config.is_cattool && (
    - + Delete +
    )} diff --git a/public/js/components/settingsPanel/Contents/MachineTranslationTab/MachineTranslationTab.js b/public/js/components/settingsPanel/Contents/MachineTranslationTab/MachineTranslationTab.js index 4f060ae8f9..01997aaca4 100644 --- a/public/js/components/settingsPanel/Contents/MachineTranslationTab/MachineTranslationTab.js +++ b/public/js/components/settingsPanel/Contents/MachineTranslationTab/MachineTranslationTab.js @@ -109,7 +109,7 @@ export const MachineTranslationTab = () => { enginesList.find((mt) => mt.id === engineIdFromQueryString) engineIdFromQueryString = false - return initialState + return initialState || undefined }) const [isAddMTEngineRequestInProgress, setIsAddMTEngineRequestInProgress] = useState(false) @@ -343,13 +343,13 @@ export const MachineTranslationTab = () => {

    Active MT

    {!config.is_cattool && !addMTVisible && ( - + )}
    diff --git a/public/js/components/settingsPanel/Contents/MachineTranslationTab/MachineTranslationTab.test.js b/public/js/components/settingsPanel/Contents/MachineTranslationTab/MachineTranslationTab.test.js index 02d26e3593..ff9e8872de 100644 --- a/public/js/components/settingsPanel/Contents/MachineTranslationTab/MachineTranslationTab.test.js +++ b/public/js/components/settingsPanel/Contents/MachineTranslationTab/MachineTranslationTab.test.js @@ -202,6 +202,12 @@ test('Delete MT Confirm', async () => { const user = userEvent.setup() global.config.isLoggedIn = true + mswServer.use( + http.post(`${config.basepath}api/app/disable-engine`, () => { + return HttpResponse.json({}) + }), + ) + const values = { mtEngines: mtEnginesMock, setMtEngines: () => {}, diff --git a/public/js/components/settingsPanel/Contents/MachineTranslationTab/MtEngines/AltLang.js b/public/js/components/settingsPanel/Contents/MachineTranslationTab/MtEngines/AltLang.js index 87a4aeb5c5..fe66792310 100644 --- a/public/js/components/settingsPanel/Contents/MachineTranslationTab/MtEngines/AltLang.js +++ b/public/js/components/settingsPanel/Contents/MachineTranslationTab/MtEngines/AltLang.js @@ -101,7 +101,6 @@ export const AltLang = ({
    @@ -133,7 +133,6 @@ export const Lara = ({
    diff --git a/public/js/components/settingsPanel/Contents/QualityFrameworkTab/CategoryRow.js b/public/js/components/settingsPanel/Contents/QualityFrameworkTab/CategoryRow.js index e2ce2419b3..88e09cb091 100644 --- a/public/js/components/settingsPanel/Contents/QualityFrameworkTab/CategoryRow.js +++ b/public/js/components/settingsPanel/Contents/QualityFrameworkTab/CategoryRow.js @@ -1,9 +1,7 @@ import React, {useContext, useEffect, useRef, useState} from 'react' import PropTypes from 'prop-types' import {QualityFrameworkTabContext} from './QualityFrameworkTab' -import {MenuButton} from '../../../common/MenuButton/MenuButton' import IconDown from '../../../icons/IconDown' -import {MenuButtonItem} from '../../../common/MenuButton/MenuButtonItem' import IconEdit from '../../../icons/IconEdit' import Trash from '../../../../../img/icons/Trash' import {SettingsPanelContext} from '../../SettingsPanelContext' @@ -12,6 +10,8 @@ import LabelWithTooltip from '../../../common/LabelWithTooltip' import {ModifyCategory} from './ModifyCategory' import {getCategoryLabelAndDescription} from './CategoriesSeveritiesTable' import ChevronDown from '../../../../../img/icons/ChevronDown' +import {DropdownMenu} from '../../../common/DropdownMenu/DropdownMenu' +import {BUTTON_MODE} from '../../../common/Button/Button' export const CategoryRow = ({category, index, shouldScrollIntoView}) => { const {portalTarget} = useContext(SettingsPanelContext) @@ -94,49 +94,66 @@ export const CategoryRow = ({category, index, shouldScrollIntoView}) => { const isDeleteDisabled = currentTemplate.categories.length === 1 const menu = ( - } - onClick={() => false} - isVisibleRectArrow={false} - itemsTarget={portalTarget} - > - setIsEditingName(true)} - data-testid="menu-button-rename" - > - - Edit - - - - Move up - - - - Move down - - - - Delete - - + + + + ), + }} + items={[ + { + label: ( + <> + + Edit + + ), + onClick: () => setIsEditingName(true), + testId: 'menu-button-rename', + }, + { + label: ( + <> +
    + +
    + Move up + + ), + disabled: isMoveUpDisabled, + onClick: moveUp, + testId: 'menu-button-moveup', + }, + { + label: ( + <> + + Move down + + ), + disabled: isMoveDownDisabled, + onClick: moveDown, + testId: 'menu-button-movedown', + }, + { + label: ( + <> + + Delete + + ), + disabled: isDeleteDisabled, + onClick: deleteCategory, + testId: 'menu-button-delete', + }, + ]} + /> ) return ( diff --git a/public/js/components/settingsPanel/Contents/QualityFrameworkTab/ModifyCategory.js b/public/js/components/settingsPanel/Contents/QualityFrameworkTab/ModifyCategory.js index 4f4069c1ca..ac02e86901 100644 --- a/public/js/components/settingsPanel/Contents/QualityFrameworkTab/ModifyCategory.js +++ b/public/js/components/settingsPanel/Contents/QualityFrameworkTab/ModifyCategory.js @@ -1,10 +1,5 @@ import React, {useContext, useEffect, useRef, useState} from 'react' -import { - BUTTON_MODE, - BUTTON_SIZE, - BUTTON_TYPE, - Button, -} from '../../../common/Button/Button' +import {BUTTON_MODE, BUTTON_TYPE, Button} from '../../../common/Button/Button' import PropTypes from 'prop-types' import Checkmark from '../../../../../img/icons/Checkmark' import {SettingsPanelContext} from '../../SettingsPanelContext' @@ -142,17 +137,12 @@ export const ModifyCategory = ({target, category, setIsEditingName}) => { {content}
    -
    - )} - {!isStandardTemplateBool && ( - - )} + {!isStandardTemplateBool && } ) : ( diff --git a/public/js/components/settingsPanel/Contents/SubTemplates/SubTemplateCreateUpdateControl.js b/public/js/components/settingsPanel/Contents/SubTemplates/SubTemplateCreateUpdateControl.js index 97f221d4b1..9acde9213e 100644 --- a/public/js/components/settingsPanel/Contents/SubTemplates/SubTemplateCreateUpdateControl.js +++ b/public/js/components/settingsPanel/Contents/SubTemplates/SubTemplateCreateUpdateControl.js @@ -16,7 +16,6 @@ export const SubTemplateCreateUpdateControl = () => { <> - diff --git a/public/js/components/settingsPanel/Contents/SubTemplates/SubTemplateMoreMenu.js b/public/js/components/settingsPanel/Contents/SubTemplates/SubTemplateMoreMenu.js index 8fbfa9915e..fb5a3ca318 100644 --- a/public/js/components/settingsPanel/Contents/SubTemplates/SubTemplateMoreMenu.js +++ b/public/js/components/settingsPanel/Contents/SubTemplates/SubTemplateMoreMenu.js @@ -1,12 +1,9 @@ import React, {useContext} from 'react' -import PropTypes from 'prop-types' import { SUBTEMPLATE_MODIFIERS, SubTemplatesContext, isStandardSubTemplate, } from './SubTemplate' -import {MenuButton} from '../../../common/MenuButton/MenuButton' -import {MenuButtonItem} from '../../../common/MenuButton/MenuButtonItem' import IconEdit from '../../../icons/IconEdit' import Trash from '../../../../../img/icons/Trash' import DotsHorizontal from '../../../../../img/icons/DotsHorizontal' @@ -15,8 +12,10 @@ import {ConfirmDeleteResourceProjectTemplates} from '../../../modals/ConfirmDele import {SettingsPanelContext} from '../../SettingsPanelContext' import {flushSync} from 'react-dom' import {SCHEMA_KEYS} from '../../../../hooks/useProjectTemplates' +import {DropdownMenu} from '../../../common/DropdownMenu/DropdownMenu' +import {BUTTON_MODE, BUTTON_SIZE} from '../../../common/Button/Button' -export const SubTemplateMoreMenu = ({portalTarget}) => { +export const SubTemplateMoreMenu = () => { const { projectTemplates, setProjectTemplates, @@ -123,40 +122,44 @@ export const SubTemplateMoreMenu = ({portalTarget}) => { } return ( - false} - icon={} - isVisibleRectArrow={false} - itemsTarget={portalTarget} - > - { - setTemplateModifier(SUBTEMPLATE_MODIFIERS.UPDATE) - setTemplateName(currentTemplate.name) - }} - > - - Rename - - - - Delete - - + + + + ), + }} + items={[ + { + label: ( + <> + + Rename + + ), + disabled: isRequestInProgress, + onClick: () => { + setTemplateModifier(SUBTEMPLATE_MODIFIERS.UPDATE) + setTemplateName(currentTemplate.name) + }, + }, + { + label: ( + <> + + Delete + + ), + disabled: isRequestInProgress, + onClick: deleteTemplateConfirmation, + testId: 'delete-template', + }, + ]} + /> ) } - -SubTemplateMoreMenu.propTypes = { - portalTarget: PropTypes.oneOfType([ - PropTypes.instanceOf(Element), - PropTypes.node, - ]), -} diff --git a/public/js/components/settingsPanel/Contents/TranslationMemoryGlossaryTab/DeleteResource.js b/public/js/components/settingsPanel/Contents/TranslationMemoryGlossaryTab/DeleteResource.js index 6354f4a683..491a74d4f3 100644 --- a/public/js/components/settingsPanel/Contents/TranslationMemoryGlossaryTab/DeleteResource.js +++ b/public/js/components/settingsPanel/Contents/TranslationMemoryGlossaryTab/DeleteResource.js @@ -3,6 +3,7 @@ import PropTypes from 'prop-types' import Checkmark from '../../../../../img/icons/Checkmark' import Close from '../../../../../img/icons/Close' +import {Button, BUTTON_SIZE, BUTTON_TYPE} from '../../../common/Button/Button' export const DeleteResource = ({row, onClose, onConfirm, footerContent}) => { const onClickConfirm = () => { @@ -26,20 +27,22 @@ export const DeleteResource = ({row, onClose, onConfirm, footerContent}) => { {footerContent}
    - + - +
    diff --git a/public/js/components/settingsPanel/Contents/TranslationMemoryGlossaryTab/ExportGlossary.js b/public/js/components/settingsPanel/Contents/TranslationMemoryGlossaryTab/ExportGlossary.js index bf8e6377c7..1cd767479b 100644 --- a/public/js/components/settingsPanel/Contents/TranslationMemoryGlossaryTab/ExportGlossary.js +++ b/public/js/components/settingsPanel/Contents/TranslationMemoryGlossaryTab/ExportGlossary.js @@ -5,6 +5,12 @@ import useExport, {EXPORT_TYPE} from './hooks/useExport' import Checkmark from '../../../../../img/icons/Checkmark' import Close from '../../../../../img/icons/Close' import CatToolActions from '../../../../actions/CatToolActions' +import { + Button, + BUTTON_HTML_TYPE, + BUTTON_SIZE, + BUTTON_TYPE, +} from '../../../common/Button/Button' export const ExportGlossary = ({row, onClose}) => { const {email, status, onSubmit, onReset} = useExport({ @@ -46,22 +52,24 @@ export const ExportGlossary = ({row, onClose}) => {
    - + - +
    diff --git a/public/js/components/settingsPanel/Contents/TranslationMemoryGlossaryTab/ExportTMX.js b/public/js/components/settingsPanel/Contents/TranslationMemoryGlossaryTab/ExportTMX.js index 4a95113edf..14920f4cc3 100644 --- a/public/js/components/settingsPanel/Contents/TranslationMemoryGlossaryTab/ExportTMX.js +++ b/public/js/components/settingsPanel/Contents/TranslationMemoryGlossaryTab/ExportTMX.js @@ -5,6 +5,12 @@ import useExport, {EXPORT_TYPE} from './hooks/useExport' import Checkmark from '../../../../../img/icons/Checkmark' import Close from '../../../../../img/icons/Close' import CatToolActions from '../../../../actions/CatToolActions' +import { + Button, + BUTTON_HTML_TYPE, + BUTTON_SIZE, + BUTTON_TYPE, +} from '../../../common/Button/Button' export const ExportTMX = ({row, onClose}) => { const {email, status, onSubmit, onReset} = useExport({ @@ -55,22 +61,24 @@ export const ExportTMX = ({row, onClose}) => {
    - + - +
    diff --git a/public/js/components/settingsPanel/Contents/TranslationMemoryGlossaryTab/ImportGlossary.js b/public/js/components/settingsPanel/Contents/TranslationMemoryGlossaryTab/ImportGlossary.js index d15516515e..2f1ef50108 100644 --- a/public/js/components/settingsPanel/Contents/TranslationMemoryGlossaryTab/ImportGlossary.js +++ b/public/js/components/settingsPanel/Contents/TranslationMemoryGlossaryTab/ImportGlossary.js @@ -4,6 +4,12 @@ import useImport, {IMPORT_TYPE} from './hooks/useImport' import Checkmark from '../../../../../img/icons/Checkmark' import Close from '../../../../../img/icons/Close' +import { + Button, + BUTTON_HTML_TYPE, + BUTTON_SIZE, + BUTTON_TYPE, +} from '../../../common/Button/Button' export const ImportGlossary = ({row, onClose}) => { const {files, uuids, status, onSubmit, onReset, onChangeFiles} = useImport({ @@ -40,12 +46,14 @@ export const ImportGlossary = ({row, onClose}) => { ) : (
    {errors[0].message} - + +
    )} @@ -81,23 +89,25 @@ export const ImportGlossary = ({row, onClose}) => {
    {files.length > 0 && ( - + )} - +
    {uuids?.length > 0 && ( diff --git a/public/js/components/settingsPanel/Contents/TranslationMemoryGlossaryTab/ImportTMX.js b/public/js/components/settingsPanel/Contents/TranslationMemoryGlossaryTab/ImportTMX.js index 0f6871fa88..e9b5e8cdb2 100644 --- a/public/js/components/settingsPanel/Contents/TranslationMemoryGlossaryTab/ImportTMX.js +++ b/public/js/components/settingsPanel/Contents/TranslationMemoryGlossaryTab/ImportTMX.js @@ -5,6 +5,12 @@ import {CreateProjectContext} from '../../../createProject/CreateProjectContext' import Checkmark from '../../../../../img/icons/Checkmark' import Close from '../../../../../img/icons/Close' +import { + Button, + BUTTON_HTML_TYPE, + BUTTON_SIZE, + BUTTON_TYPE, +} from '../../../common/Button/Button' export const ImportTMX = ({row, onClose}) => { const {setIsImportTMXInProgress} = useContext(CreateProjectContext) @@ -52,12 +58,13 @@ export const ImportTMX = ({row, onClose}) => { ) : (
    {errors.message} - + +
    )} @@ -84,23 +91,24 @@ export const ImportTMX = ({row, onClose}) => {
    {files.length > 0 && ( - + )} - - +
    {uuids?.length > 0 && ( diff --git a/public/js/components/settingsPanel/Contents/TranslationMemoryGlossaryTab/ShareResource.js b/public/js/components/settingsPanel/Contents/TranslationMemoryGlossaryTab/ShareResource.js index 10a899c131..dd5be020fe 100644 --- a/public/js/components/settingsPanel/Contents/TranslationMemoryGlossaryTab/ShareResource.js +++ b/public/js/components/settingsPanel/Contents/TranslationMemoryGlossaryTab/ShareResource.js @@ -9,6 +9,12 @@ import ModalsActions from '../../../../actions/ModalsActions' import ShareTmModal from '../../../modals/ShareTmModal' import CatToolActions from '../../../../actions/CatToolActions' import UserStore from '../../../../stores/UserStore' +import { + Button, + BUTTON_HTML_TYPE, + BUTTON_SIZE, + BUTTON_TYPE, +} from '../../../common/Button/Button' export const ShareResource = ({row, onClose, onShare}) => { const [emails, setEmails] = useState('') @@ -149,21 +155,23 @@ export const ShareResource = ({row, onClose, onShare}) => { />
    - + - +
    diff --git a/public/js/components/settingsPanel/Contents/TranslationMemoryGlossaryTab/TMCreateResourceRow.js b/public/js/components/settingsPanel/Contents/TranslationMemoryGlossaryTab/TMCreateResourceRow.js index 07c04ee2d5..4f8ba52585 100644 --- a/public/js/components/settingsPanel/Contents/TranslationMemoryGlossaryTab/TMCreateResourceRow.js +++ b/public/js/components/settingsPanel/Contents/TranslationMemoryGlossaryTab/TMCreateResourceRow.js @@ -14,6 +14,12 @@ import {getInfoTmKey} from '../../../../api/getInfoTmKey' import Checkmark from '../../../../../img/icons/Checkmark' import Close from '../../../../../img/icons/Close' import CatToolActions from '../../../../actions/CatToolActions' +import { + Button, + BUTTON_HTML_TYPE, + BUTTON_SIZE, + BUTTON_TYPE, +} from '../../../common/Button/Button' export const TMCreateResourceRow = ({row}) => { const {tmKeys, setTmKeys, modifyingCurrentTemplate} = @@ -350,22 +356,25 @@ export const TMCreateResourceRow = ({row}) => {
    - - +
    ) diff --git a/public/js/components/settingsPanel/Contents/TranslationMemoryGlossaryTab/TMKeyRow.js b/public/js/components/settingsPanel/Contents/TranslationMemoryGlossaryTab/TMKeyRow.js index e3764955a5..466d0cf1d9 100644 --- a/public/js/components/settingsPanel/Contents/TranslationMemoryGlossaryTab/TMKeyRow.js +++ b/public/js/components/settingsPanel/Contents/TranslationMemoryGlossaryTab/TMKeyRow.js @@ -8,8 +8,6 @@ import { isOwnerOfKey, orderTmKeys, } from './TranslationMemoryGlossaryTab' -import {MenuButton} from '../../../common/MenuButton/MenuButton' -import {MenuButtonItem} from '../../../common/MenuButton/MenuButtonItem' import {ImportTMX} from './ImportTMX' import {ImportGlossary} from './ImportGlossary' import {ExportTMX} from './ExportTMX' @@ -38,6 +36,10 @@ import {NumericStepper} from '../../../common/NumericStepper/NumericStepper' import IconClose from '../../../icons/IconClose' import {getTmKeyEnginesInfo} from '../../../../api/getTmKeyEnginesInfo/getTmKeyEnginesInfo' import Globe from '../../../../../img/icons/Globe' +import { + DROPDOWN_MENU_ALIGN, + DropdownMenu, +} from '../../../common/DropdownMenu/DropdownMenu' export const TMKeyRow = ({row, onExpandRow}) => { const {isImportTMXInProgress} = useContext(CreateProjectContext) @@ -475,7 +477,7 @@ export const TMKeyRow = ({row, onExpandRow}) => { stepValue={1} />
    ) : ( + + + + ), + }} + items={[ + { + label: ( + <> + Import termbase + + ), + onClick: () => handleExpandeRow(ImportGlossary), + testId: 'import-glossary', + }, + { + label: ( + <> + Export TMX + + ), + onClick: () => handleExpandeRow(ExportTMX), + testId: 'export-tmx', + }, + { + label: ( + <> + Export termbase + + ), + onClick: () => handleExpandeRow(ExportGlossary), + testId: 'export-glossary', + }, + { + label: ( + <> + Share resource + + ), + onClick: () => handleExpandeRow(ShareResource), + testId: 'share-resource', + }, + { + label: ( + <> + Delete resource + + ), + onClick: showConfirmDelete, + testId: 'delete-resource', + }, + ]} + />
    ) : isMMSharedKey && !config.not_empty_default_tm_key ? (
    - +
    ) : (
    diff --git a/public/js/components/settingsPanel/Contents/TranslationMemoryGlossaryTab/TranslationMemoryGlossaryTab.js b/public/js/components/settingsPanel/Contents/TranslationMemoryGlossaryTab/TranslationMemoryGlossaryTab.js index f9d0c89b28..a0f10c957e 100644 --- a/public/js/components/settingsPanel/Contents/TranslationMemoryGlossaryTab/TranslationMemoryGlossaryTab.js +++ b/public/js/components/settingsPanel/Contents/TranslationMemoryGlossaryTab/TranslationMemoryGlossaryTab.js @@ -20,6 +20,7 @@ import {METADATA_KEY} from '../../../../constants/Constants' import {updateJobMetadata} from '../../../../api/updateJobMetadata/updateJobMetadata' import IconAdd from '../../../icons/IconAdd' import UsersPlus from '../../../../../img/icons/UsersPlus' +import {Button, BUTTON_TYPE} from '../../../common/Button/Button' const COLUMNS_TABLE_ACTIVE = [ {name: 'Lookup'}, @@ -489,21 +490,21 @@ export const TranslationMemoryGlossaryTab = () => {

    Active Resources

    - + - +
    { + console.error = (...args) => { + if ( + typeof args[0] === 'string' && + args[0].includes('not configured to support act') + ) { + return + } + originalConsoleError(...args) + } + + window.ResizeObserver = ResizeObserver + return (window.open = jest.fn()) +}) +afterAll(() => { + console.error = originalConsoleError +}) + global.config = { basepath: 'http://localhost/', enableMultiDomainApi: false, @@ -342,7 +370,7 @@ test('Create and delete new resource', async () => { expect(rowNewEntry.update).toBeChecked() // delete - const menuButton = screen.getByTestId('menu-button-show-items') + const menuButton = screen.getByTestId('tm-row-menu') await act(async () => user.click(menuButton)) @@ -434,9 +462,9 @@ test('Row Menu items', async () => { rerender() - const menuButton = screen.getByTestId('menu-button-show-items') + const menuButton = screen.getByTestId('tm-row-menu') - await act(async () => user.click(screen.getByTestId('menu-button'))) + await act(async () => user.click(screen.getByTestId('tm-row-import-tmx'))) expect(screen.getByText('Select a tmx file to import')).toBeInTheDocument() await act(async () => user.click(menuButton)) @@ -559,7 +587,7 @@ test('Modal delete tmkeys used in other templates', async () => { render() - const menuButton = screen.getByTestId('menu-button-show-items') + const menuButton = screen.getByTestId('tm-row-menu') await act(async () => user.click(menuButton)) diff --git a/public/js/components/settingsPanel/ProjectTemplate/CreateUpdateControl.js b/public/js/components/settingsPanel/ProjectTemplate/CreateUpdateControl.js index d53226d543..f002a02d5a 100644 --- a/public/js/components/settingsPanel/ProjectTemplate/CreateUpdateControl.js +++ b/public/js/components/settingsPanel/ProjectTemplate/CreateUpdateControl.js @@ -18,7 +18,7 @@ export const CreateUpdateControl = () => { )} - {!isStandardTemplateBool && } + {!isStandardTemplateBool && } ) : ( @@ -411,10 +410,3 @@ export const ProjectTemplate = ({portalTarget}) => { ) } - -ProjectTemplate.propTypes = { - portalTarget: PropTypes.oneOfType([ - PropTypes.instanceOf(Element), - PropTypes.node, - ]), -} diff --git a/public/js/components/settingsPanel/ProjectTemplate/ProjectTemplate.test.js b/public/js/components/settingsPanel/ProjectTemplate/ProjectTemplate.test.js index 9c43690884..a40342145b 100644 --- a/public/js/components/settingsPanel/ProjectTemplate/ProjectTemplate.test.js +++ b/public/js/components/settingsPanel/ProjectTemplate/ProjectTemplate.test.js @@ -18,19 +18,20 @@ global.config = { isLoggedIn: 1, } -const wrapperElement = document.createElement('div') -const WrapperComponent = (contextProps) => { - const ref = useRef() - - useEffect(() => { - ref.current.appendChild(wrapperElement) - }, []) +class ResizeObserver { + observe() {} + unobserve() {} + disconnect() {} +} +beforeAll(() => { + window.ResizeObserver = ResizeObserver + return (window.open = jest.fn()) +}) +const WrapperComponent = (contextProps) => { return ( -
    - -
    +
    ) } @@ -269,7 +270,7 @@ test('Create, update and delete template', async () => { // delete await act(async () => - user.click(screen.getByTestId('menu-button-show-items')), + user.click(screen.getByTestId('project-template-more-menu')), ) await waitFor(async () => user.click(screen.getByTestId('delete-template'))) diff --git a/public/js/components/settingsPanel/SettingsPanel.js b/public/js/components/settingsPanel/SettingsPanel.js index bd265c1b1c..b63efe1f04 100644 --- a/public/js/components/settingsPanel/SettingsPanel.js +++ b/public/js/components/settingsPanel/SettingsPanel.js @@ -21,6 +21,13 @@ import defaultFiltersParams from './Contents/defaultTemplates/filterParams.json' import {isEqual} from 'lodash' import useSyncTemplateWithConvertFile from './useSyncTemplateWithConvertFile' import {EditorOtherTab} from './Contents/EditorOtherTab' +import { + Button, + BUTTON_MODE, + BUTTON_SIZE, + BUTTON_TYPE, +} from '../common/Button/Button' +import Close from '../../../img/icons/Close' let tabOpenFromQueryString = new URLSearchParams(window.location.search).get( 'openTab', @@ -368,7 +375,14 @@ export const SettingsPanel = ({
    Settings -
    +
    {isEnabledProjectTemplateComponent && } {currentProjectTemplate && } diff --git a/public/js/components/xliffToTarget/UploadXliff.js b/public/js/components/xliffToTarget/UploadXliff.js index bb63758254..ab39f7ec26 100644 --- a/public/js/components/xliffToTarget/UploadXliff.js +++ b/public/js/components/xliffToTarget/UploadXliff.js @@ -203,9 +203,7 @@ export const UploadXliff = () => { {files.map((f, idx) => (
    - + {CommonUtils.getFileIcon(f.ext)} {f.name}
    {f.error && ( @@ -236,7 +234,7 @@ export const UploadXliff = () => {
    )}
    -
    - - More settings +
    +
    @@ -1062,79 +1067,80 @@ const NewProject = () => {
    )} -
    -
    - {conversionEnabled && ( -

    - Matecat supports{' '} - { - ModalsActions.showModalComponent( - SupportedFilesModal, - {supportedFiles: supportedFiles}, - 'Supported file formats', - {minWidth: '80%', height: '80%'}, - ) - }} - > - {formatsNumber} file formats{' '} - - . - {isGDriveEnabled && - currentProjectTemplate && - uploadedFilesNames.length === 0 && ( - - and{' '} - setOpenGDrive(true)} - href="#" - > - Google Drive files{' '} - - - - )} -

    - )} -
    - {!projectSent ? ( - - ) : ( - <> +
    + {conversionEnabled && ( +

    + Matecat supports{' '} + { + ModalsActions.showModalComponent( + SupportedFilesModal, + {supportedFiles: supportedFiles}, + 'Supported file formats', + {minWidth: '80%', height: '80%'}, + ) + }} + > + {formatsNumber} file formats{' '} + + . + {isGDriveEnabled && + currentProjectTemplate && + uploadedFilesNames.length === 0 && ( + + and{' '} + setOpenGDrive(true)} + href="#" + > + Google Drive files{' '} + + + + )} +

    + )} +
    + {!projectSent ? ( - - )} + ) : ( + <> + + + )} +
    + {isOpenMultiselectLanguages && ( { desktop with the browser of your choice.

    diff --git a/public/js/pages/QualityReport.js b/public/js/pages/QualityReport.js index f3f50df000..91b1be0b68 100644 --- a/public/js/pages/QualityReport.js +++ b/public/js/pages/QualityReport.js @@ -11,8 +11,8 @@ import {ApplicationWrapperContext} from '../components/common/ApplicationWrapper import {CookieConsent} from '../components/common/CookieConsent' import {mountPage} from './mountPage' import SocketListener from '../sse/SocketListener' -import {DropdownMenu} from '../components/common/DropdownMenu/DropdownMenu' -import {BUTTON_SIZE} from '../components/common/Button/Button' +import {SegmentedControl} from '../components/common/SegmentedControl' +import {SpinnerLoader} from '../components/common/SpinnerLoader' const getReviseUrlParameter = () => { const url = new URL(window.location.href) @@ -20,6 +20,27 @@ const getReviseUrlParameter = () => { return revType ? revType : '1' } +const SEGMENTED_CONTROL_OPTIONS = [ + { + id: '1', + name: ( + <> +
    + Revise + + ), + }, + { + id: '2', + name: ( + <> +
    + Revise 2 + + ), + }, +] + export const QualityReport = () => { const {isUserLogged, userInfo} = useContext(ApplicationWrapperContext) @@ -148,130 +169,21 @@ export const QualityReport = () => {
    {jobInfo ? ( -
    +
    -

    QR Job summary

    +

    Quality report

    {secondPassReviewEnabled ? (
    - - {revisionToShow === '1' ? ( -
    -
    - Revision -
    - ) : ( -
    -
    - 2nd Revision -
    - )} -
    - ), - size: BUTTON_SIZE.ICON_STANDARD, - }} - items={[ - { - label: ( - <> -
    - Revision - - ), - onClick: () => { - setRevisionToShow('1') - }, - }, - { - label: ( - <> -
    - 2nd Revision - - ), - onClick: () => { - setRevisionToShow('2') - }, - }, - ]} + setRevisionToShow(v)} /> - {/*
    - {revisionToShow === '1' ? ( -
    -
    - Revision -
    - ) : ( -
    -
    - 2nd Revision -
    - )} - -
    -
    -
    - Revision -
    -
    -
    - 2nd Revision -
    -
    -
    */}
    @@ -299,9 +211,7 @@ export const QualityReport = () => {
    ) : (
    -
    -
    Loading
    -
    +
    )}
    diff --git a/public/js/pages/QualityReport.test.js b/public/js/pages/QualityReport.test.js index 0aadd6c1f9..721c38deb0 100644 --- a/public/js/pages/QualityReport.test.js +++ b/public/js/pages/QualityReport.test.js @@ -1334,6 +1334,6 @@ test('renders properly', async () => { // expect(screen.getByText('Loading')).toBeVisible() await waitFor(() => { - expect(screen.getByText('QR Job summary')).toBeVisible() + expect(screen.getByText('Quality report')).toBeVisible() }) }) diff --git a/public/js/utils/commonUtils.js b/public/js/utils/commonUtils.js index 645d00e1d6..1b98cbcd52 100644 --- a/public/js/utils/commonUtils.js +++ b/public/js/utils/commonUtils.js @@ -1,3 +1,4 @@ +import React from 'react' import Cookies from 'js-cookie' import $ from 'jquery' import OfflineUtils from './offlineUtils' @@ -6,6 +7,18 @@ import SegmentStore from '../stores/SegmentStore' import AlertModal from '../components/modals/AlertModal' import ModalsActions from '../actions/ModalsActions' import {isTranslationTailEmpty} from '../setTranslationUtil' +import FileTypeText from '../../img/icons/FileTypeText' +import FileTypePresentation from '../../img/icons/FileTypePresentation' +import FileTypeHtml from '../../img/icons/FileTypeHtml' +import FileTypePdf from '../../img/icons/FileTypePdf' +import FileTypeXls from '../../img/icons/FileTypeXls' +import FileTypeFile from '../../img/icons/FileTypeFile' +import FileTypeXliff from '../../img/icons/FileTypeXliff' +import FileTypeZip from '../../img/icons/FileTypeZip' +import FileTypeCode from '../../img/icons/FileTypeCode' +import FileTypeImage from '../../img/icons/FileTypeImage' +import FileTypeSub from '../../img/icons/FileTypeSub' +import FileTypePub from '../../img/icons/FileTypePub' const CommonUtils = { millisecondsToTime(milli) { @@ -178,7 +191,7 @@ const CommonUtils = { } }, - getIconClass: function (ext) { + getFileIcon: function (ext, size = 24) { switch (ext) { case 'doc': case 'dot': @@ -188,8 +201,9 @@ const CommonUtils = { case 'dotm': case 'odt': case 'sxw': - return 'extdoc' - case 'pot': + case 'pages': + case 'ott': + return case 'pps': case 'ppt': case 'potm': @@ -199,13 +213,15 @@ const CommonUtils = { case 'pptm': case 'pptx': case 'odp': - case 'sxi': - return 'extppt' + case 'key': + case 'otp': + return case 'htm': case 'html': - return 'exthtm' + case 'xhtml': + return case 'pdf': - return 'extpdf' + return case 'xls': case 'xlt': case 'xlsm': @@ -214,42 +230,71 @@ const CommonUtils = { case 'ods': case 'sxc': case 'csv': - return 'extxls' + case 'numbers': + case 'xltm': + case 'ots': + case 'tsv': + return + case 'sbv': + case 'srt': + case 'vtt': + return + case 'avif': + case 'bmp': + case 'png': + case 'gif': + case 'jpeg': + case 'jpg': + case 'heic': + case 'heif': + case 'jfif': + case 'tif': + case 'tiff': + case 'webp': + return case 'txt': - return 'exttxt' - case 'ttx': - return 'extttx' - case 'itd': - return 'extitd' + return case 'xlf': - return 'extxlf' + case 'ttx': + case 'xliff': + case 'sdlxliff': + case 'tmx': + case 'po': + case 'g': + case 'ts': + case 'pot': + return case 'mif': - return 'extmif' case 'idml': - return 'extidd' - case 'xtg': - return 'extqxp' + case 'icml': + case 'tex': + return //TODO add specific icons for these file types + case 'zip': + return case 'xml': - case 'x-jsont2': + case 'Android xml': + case 'dtd': case 'json': + case 'x-jsont2': + case 'jsont2': case 'jsont': case 'yaml': case 'yml': - return 'extxml' - case 'rc': - return 'extrcc' - case 'resx': - return 'extres' - case 'sgml': - return 'extsgl' - case 'sgm': - return 'extsgm' case 'properties': - return 'extpro' - case 'zip': - return 'extzip' + case 'resx': + case 'strings': + case 'markdown': + case 'md': + case 'dita': + case 'wix': + case 'ditamap': + case 'php': + case 'xini': + case 'sxml': + case 'txml': + return default: - return 'exttxt' + return } }, @@ -473,7 +518,7 @@ const CommonUtils = { // Format the Date object using toLocaleString. return { day: dd.getDate().toString(), - month: dd.toLocaleString('default', {month: 'long'}), + month: dd.toLocaleString('default', {month: 'short'}), time: dd.toLocaleTimeString('en-US', { hour12: true, hour: '2-digit',