Skip to content

Commit

Permalink
Merge branch 'main' into features/Hexlet#159
Browse files Browse the repository at this point in the history
  • Loading branch information
d1z3d authored Aug 26, 2024
2 parents 964714f + 888f381 commit 609e049
Show file tree
Hide file tree
Showing 9 changed files with 102 additions and 66 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,11 @@
import jakarta.validation.Constraint;
import jakarta.validation.Payload;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
* Validation annotation to validate that 2 fields have the same value.
* An array of fields and their matching confirmation fields can be supplied.
Expand All @@ -27,6 +24,8 @@
* message = "The password and it confirmation must match")}
*/
@Constraint(validatedBy = FieldMatchConsiderCaseValidator.class)
@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface FieldMatchConsiderCase {

String message() default "The {first} and {second} fields must be equal";
Expand All @@ -45,16 +44,4 @@
*/
String second();

/**
* Defines several <code>@FieldMatch</code> annotations on the same element
*
* @see FieldMatchConsiderCase
*/
@Target({TYPE, ANNOTATION_TYPE})
@Retention(RUNTIME)
@Documented
@interface List {

FieldMatchConsiderCase[] value();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
@FieldMatchConsiderCase(
first = "password",
second = "confirmPassword",
message = "The password and it confirmation must match")
message = "{alert.passwords-dont-match}")
@ToString
public class SignupAccountModel {

Expand Down
2 changes: 2 additions & 0 deletions src/main/resources/messages_en.properties
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ wks.placeholder.descr=Workspace Description
wks.info=Info
wks.typos=Typos
wks.users=Users
wks.users.email-placeholder=Enter user email. For example: [email protected]
wks.settings=Settings
wks.urls=URLs
wks.integration=Integration
Expand Down Expand Up @@ -107,3 +108,4 @@ btn.delete-from-wks=Delete from workspace
alert.password-wrong-format=Password must be between 8 and 20 characters \
and contain only latin letters, digits and symbols ~`!@#$%^&*()_-+={[}]|\:;"'<,>.?/
link.sign-in-with-github=Sign in with GitHub
alert.passwords-dont-match=Confirmation does not match the password
2 changes: 2 additions & 0 deletions src/main/resources/messages_ru.properties
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ wks.placeholder.descr=Описание Пространства
wks.info=Информация
wks.typos=Опечатки
wks.users=Пользователи
wks.users.email-placeholder=Введите адрес электронной почты пользователя. Например: [email protected]
wks.settings=Настройки
wks.urls=Домены
wks.integration=Интеграция
Expand Down Expand Up @@ -105,3 +106,4 @@ alert.password-wrong-format=Пароль должен быть от 8 до 20 с
\ и содержать только буквы латинского алфавита,\
\ цифры и символы ~`!@#$%^&*()_-+={[}]|\:;"'<,>.?/
link.sign-in-with-github=Войти с помощью: GitHub
alert.passwords-dont-match=Подтверждение не совпадает с паролем
30 changes: 22 additions & 8 deletions src/main/resources/templates/workspace/wks-integration.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,33 @@
<main class="container-fluid">
<div class="row">
<div class="col-2" th:insert="fragments/panels :: workspaceSideBar (${wksId}, ${wksName}, 'integration')"></div>
<div class="col">
<div class="col-10">
<div class="row mt-4">
<div class="col">
<p class="fw-bold mb-2"th:text="#{text.script-descr}"></p>
<pre style="font-size:18px" class="form-control user-select-all d-inline-flex mb-3" readonly>
&lt;script src="https://cdn.jsdelivr.net/gh/hexlet/hexlet-correction@main/src/widget/index.js"&gt;&lt;/script&gt;;

&lt;script&gt;
handleTypoReporter({ authorizationToken: '[[${wksBasicToken}]]',
workSpaceUrl: '[[${rootUrl}]]', workSpaceId: '[[${wksId}]]'})
&lt;/script&gt;</pre>
</div>
</div>
function loadScript(src, callback) {
const body = document.querySelector('body')
const script = document.createElement('script');
script.src = src;
script.onload = callback;
body.appendChild(script);
};

document.addEventListener('DOMContentLoaded', function () {
const scriptSrc = 'https://cdn.jsdelivr.net/gh/hexlet/hexlet-correction@latest/src/widget/index.js?v=' + new Date().getTime();
loadScript(scriptSrc, function () {
handleTypoReporter({
authorizationToken: '[[${wksBasicToken}]]',
workSpaceUrl: '[[${rootUrl}]]',
workSpaceId: '[[${wksId}]]'})
});
});
&lt;/script&gt;
</pre>
</div>
</div>
</div>
</div>
</main>
Expand Down
24 changes: 4 additions & 20 deletions src/main/resources/templates/workspace/wks-users.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
<form method="POST" th:action="@{'/workspace/' + ${wksId} + '/users'}" th:object="${inputEmail}">
<div class="form-group">
<input type="email" class="form-control" id="inputUserEmail"
placeholder="Enter user email. For example: [email protected]" th:field="*{email}"
th:placeholder="#{wks.users.email-placeholder}" th:field="*{email}"
th:classappend="${!#fields.hasErrors('email') && formModified}? 'is-valid'"
th:errorclass="is-invalid" required>
<div class="invalid-feedback" th:if="${#fields.hasErrors('email')}">
Expand Down Expand Up @@ -103,7 +103,7 @@
<tbody>
<th:block th:each="userInfo : ${userPage.content}" th:object="${userInfo}">
<!-- Workspace user table row -->
<tr aria-expanded="false" class="accordion collapsed" data-bs-toggle="collapse">
<tr>
<td th:text="*{id}"></td>
<td th:text="*{firstName}"></td>
<td th:text="*{lastName}"></td>
Expand All @@ -121,24 +121,8 @@
</td>
</tr>
<!-- Workspace user table row collapsed part -->
<tr>
<td class="p-0" colspan="7">
<div class="accordion-collapse collapse" th:id="|collapseUserRowId_*{id}|">
<div class="p-4">
<div class="row mb-2">
<!-- Workspace user table row delete buttons -->
<div class="col-1">
<form th:action="@{'/users/' + *{id}(wksId=${wksId})}"
th:method="delete">
<button class="btn btn-danger" type="submit">Delete
</button>
</form>
</div>
</div>
</div>
</div>
</td>
</tr>
<!-- Deleted -->
<!-- TODO add possibility for admin to leave workspace (i.e. delete himself from wks), like in posthog service -->
</th:block>
</tbody>
</table>
Expand Down
39 changes: 35 additions & 4 deletions src/test/java/io/hexlet/typoreporter/web/SignupControllerIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,26 @@
import io.hexlet.typoreporter.repository.AccountRepository;
import io.hexlet.typoreporter.test.DBUnitEnumPostgres;
import io.hexlet.typoreporter.web.model.SignupAccountModel;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.transaction.annotation.Transactional;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.containers.PostgreSQLContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;

import static com.github.database.rider.core.api.configuration.Orthography.LOWERCASE;
import static io.hexlet.typoreporter.test.Constraints.POSTGRES_IMAGE;
import static io.hexlet.typoreporter.test.factory.EntitiesFactory.ACCOUNT_INCORRECT_EMAIL;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.assertj.core.api.Assertions.assertThat;
import static io.hexlet.typoreporter.test.Constraints.POSTGRES_IMAGE;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@SpringBootTest
Expand Down Expand Up @@ -66,6 +68,14 @@ static void datasourceProperties(DynamicPropertyRegistry registry) {
"another_password", "another_password",
"another_firstName", "another_lastName");

private static ResourceBundleMessageSource source;

@BeforeAll
static void init() {
source = new ResourceBundleMessageSource();
source.setBasename("messages_en");
}

@Test
void createAccountWithIgnoreEmailCase() throws Exception {
assertThat(accountRepository.count()).isEqualTo(0L);
Expand Down Expand Up @@ -140,4 +150,25 @@ void signupInAccountWithBadEmail() throws Exception {
var body = response.getResponse().getContentAsString();
assertThat(body).contains(String.format("The email &quot;%s&quot; is not valid", ACCOUNT_INCORRECT_EMAIL));
}

@Test
void signupInPasswordsDontMatch() throws Exception {
model.setConfirmPassword("WrongPassword123");
var response = mockMvc.perform(post("/signup")
.param("username", model.getUsername())
.param("email", model.getEmail())
.param("password", model.getPassword())
.param("confirmPassword", model.getConfirmPassword())
.param("firstName", model.getFirstName())
.param("lastName", model.getLastName())
.with(csrf()))
.andReturn();
var body = response.getResponse().getContentAsString();
var result = accountRepository.findAccountByEmail(model.getEmail().toLowerCase());

assertThat(body).contains(source.getMessage("alert.passwords-dont-match", null, null));
assertThat(result).isEmpty();

}

}
23 changes: 19 additions & 4 deletions src/widget/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -216,11 +216,26 @@ <h2 class="text-body-emphasis">Guides</h2>
Created by the Bootstrap team · © 2023
</footer>
</div>
<script src="../assets/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://cdn.jsdelivr.net/gh/hexlet/hexlet-correction@main/src/widget/index.js"></script>
<script src="../assets/dist/js/bootstrap.bundle.min.js"></script>
<script>
handleTypoReporter({ authorizationToken: 'MjQyOmVlYTZkMWE1LTNkMGQtNDg1Yi04OGMwLWVkOGU1YTRlOGZjMA==',
workSpaceUrl: 'https://hexlet-correction.herokuapp.com', workSpaceId: '242'})
function loadScript(src, callback) {
const body = document.querySelector('body')
const script = document.createElement('script');
script.src = src;
script.onload = callback;
body.appendChild(script);
};

document.addEventListener('DOMContentLoaded', function () {
const scriptSrc = 'https://cdn.jsdelivr.net/gh/hexlet/hexlet-correction@latest/src/widget/index.js?v=' + new Date().getTime();
loadScript(scriptSrc, function () {
handleTypoReporter({
authorizationToken: 'MjQyOmVlYTZkMWE1LTNkMGQtNDg1Yi04OGMwLWVkOGU1YTRlOGZjMA==',
workSpaceUrl: 'https://fixit.hexlet.io',
workSpaceId: '242'
})
});
});
</script>
</body>
</html>
25 changes: 13 additions & 12 deletions src/widget/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -238,13 +238,13 @@ const sendData = (elements, state) => async (event) => {

const view = (elements, state) => {
const watch = (state, callback) => new Proxy(state, {
set(target, prop, value) {
const prevValue = target[prop];
const result = Reflect.set(target, prop, value);
callback(prop, value, prevValue);
return result;
},
});
set(target, prop, value) {
const prevValue = target[prop];
const result = Reflect.set(target, prop, value);
callback(prop, value, prevValue);
return result;
},
});

const watchedState = watch(state, (path) => {
switch (path) {
Expand All @@ -258,17 +258,18 @@ const view = (elements, state) => {
});

return watchedState;
}
};

const isSelectionLeftToRight = (selection) => {
const range = document.createRange();
range.setStart(selection.focusNode, selection.focusOffset);
range.setEnd(selection.anchorNode, selection.anchorOffset);
return range.collapsed;
}
};

const handleTypoReporter = (options) => {
if (!options || !options.authorizationToken && !options.workSpaceId) {
console.log('commit 6ced041');
if (!options || (!options.authorizationToken && !options.workSpaceId)) {
throw new Error('Для работы модуля требуется указать workSpaceId и authorizationToken');
}

Expand Down Expand Up @@ -307,13 +308,13 @@ const handleTypoReporter = (options) => {
const maxLength = 50;
state.data.textTypo = selection.toString();

if(isSelectionLeftToRight(selection)) {
if (isSelectionLeftToRight(selection)) {
const start = Math.max(anchorOffset - maxLength, 0);
const end = Math.min(focusOffset + maxLength, anchorNode.length);
state.data.textBeforeTypo = anchorNode.textContent.substring(start, anchorOffset);
state.data.textAfterTypo = anchorNode.substringData(focusOffset, end - focusOffset);
} else {
const start = Math.max(focusOffset - maxLength, 0);
const start = Math.max(focusOffset - maxLength, 0);
const end = Math.min(anchorOffset + maxLength, anchorNode.length);
state.data.textBeforeTypo = anchorNode.textContent.substring(start, focusOffset);
state.data.textAfterTypo = anchorNode.substringData(anchorOffset, end - anchorOffset);
Expand Down

0 comments on commit 609e049

Please sign in to comment.