lista de usuarios terminada

This commit is contained in:
2025-09-26 17:57:06 +02:00
parent 01a1ac4b71
commit 88b43847f0
29 changed files with 27681 additions and 138 deletions

View File

@ -22,7 +22,7 @@ public class InternationalizationConfig implements WebMvcConfigurer {
@Bean
public LocaleResolver localeResolver() {
SessionLocaleResolver slr = new SessionLocaleResolver();
slr.setDefaultLocale(Locale.forLanguageTag("es")); // idioma por defecto
slr.setDefaultLocale(Locale.forLanguageTag("es-ES")); // idioma por defecto
return slr;
}

View File

@ -6,6 +6,8 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
@ -22,84 +24,107 @@ import com.imprimelibros.erp.users.UserDetailsImpl;
@Configuration
public class SecurityConfig {
private final DataSource dataSource;
private final DataSource dataSource;
public SecurityConfig(DataSource dataSource) {
this.dataSource = dataSource;
}
public SecurityConfig(DataSource dataSource) {
this.dataSource = dataSource;
}
// UserDetailsService para autenticación por username
@Bean
public UserDetailsService userDetailsService(UserDao repo) {
return username -> {
User u = repo.findByUserNameAndEnabledTrue(username);
if (u == null)
throw new UsernameNotFoundException("No existe: " + username);
return new UserDetailsImpl(u);
};
}
// ========== Beans base ==========
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public UserDetailsService userDetailsService(UserDao repo) {
return username -> {
User u = repo.findByUserNameAndEnabledTrue(username);
if (u == null) throw new UsernameNotFoundException("No existe: " + username);
return new UserDetailsImpl(u);
};
}
// Repositorio de tokens persistentes (usa la tabla 'persistent_logins')
@Bean
public PersistentTokenRepository persistentTokenRepository() {
JdbcTokenRepositoryImpl repo = new JdbcTokenRepositoryImpl();
repo.setDataSource(dataSource);
// Descomenta una única vez si quieres que cree la tabla automáticamente:
// repo.setCreateTableOnStartup(true);
return repo;
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http, @Value("${security.rememberme.key}") String keyRememberMe) throws Exception {
http
.sessionManagement(session -> session
.invalidSessionUrl("/login?expired")
.maximumSessions(1) // opcional: limita sesiones concurrentes
)
// CSRF habilitado; ignoramos endpoints públicos del presupuesto (AJAX)
.csrf(csrf -> csrf.ignoringRequestMatchers("/presupuesto/public/**"))
// Provider que soporta UsernamePasswordAuthenticationToken
@Bean
public AuthenticationProvider daoAuthenticationProvider(
UserDetailsService userDetailsService,
PasswordEncoder passwordEncoder) {
.authorizeHttpRequests(auth -> auth
.requestMatchers(
"/", "/login",
"/assets/**", "/css/**", "/js/**", "/images/**",
"/public/**", "/presupuesto/public/**",
"/error", "/favicon.ico")
.permitAll()
.anyRequest().authenticated())
DaoAuthenticationProvider p = new DaoAuthenticationProvider();
p.setUserDetailsService(userDetailsService);
p.setPasswordEncoder(passwordEncoder);
return p;
}
.authorizeHttpRequests(configurer -> configurer
.requestMatchers("/users/**").hasAnyRole("SUPERADMIN", "ADMIN")
)
.formLogin(login -> login
.loginPage("/login").permitAll()
.loginProcessingUrl("/login")
.usernameParameter("username")
.passwordParameter("password")
.defaultSuccessUrl("/", true))
// Remember-me (tabla persistent_logins)
@Bean
public PersistentTokenRepository persistentTokenRepository() {
JdbcTokenRepositoryImpl repo = new JdbcTokenRepositoryImpl();
repo.setDataSource(dataSource);
// repo.setCreateTableOnStartup(true); // solo 1ª vez si necesitas crear la tabla
return repo;
}
// ===== Remember Me =====
.rememberMe(rm -> rm
.key(keyRememberMe) // clave secreta
.rememberMeParameter("remember-me") // <input name="remember-me">
.rememberMeCookieName("IMPRIMELIBROS_REMEMBER")
.tokenValiditySeconds(60 * 60 * 24 * 14) // 14 días
.userDetailsService(userDetailsService(null)) // se inyecta el bean real
// en runtime
.tokenRepository(persistentTokenRepository()))
// ========== Filtro de seguridad ==========
@Bean
public SecurityFilterChain securityFilterChain(
HttpSecurity http,
@Value("${security.rememberme.key}") String keyRememberMe,
UserDetailsService userDetailsService,
PersistentTokenRepository tokenRepo,
AuthenticationProvider daoAuthenticationProvider
) throws Exception {
.logout(logout -> logout
.logoutUrl("/logout")
.logoutSuccessUrl("/")
.invalidateHttpSession(true)
.deleteCookies("JSESSIONID", "IMPRIMELIBROS_REMEMBER")
.permitAll());
http
// Registra explícitamente el provider para Username/Password
.authenticationProvider(daoAuthenticationProvider)
return http.build();
}
.sessionManagement(session -> session
.invalidSessionUrl("/login?expired")
.maximumSessions(1)
)
.csrf(csrf -> csrf
.ignoringRequestMatchers("/presupuesto/public/**")
)
.authorizeHttpRequests(auth -> auth
.requestMatchers("/", "/login",
"/assets/**", "/css/**", "/js/**", "/images/**",
"/public/**", "/presupuesto/public/**",
"/error", "/favicon.ico").permitAll()
.requestMatchers("/users/**").hasAnyRole("SUPERADMIN", "ADMIN")
.anyRequest().authenticated()
)
.formLogin(login -> login
.loginPage("/login").permitAll()
.loginProcessingUrl("/login")
.usernameParameter("username")
.passwordParameter("password")
.defaultSuccessUrl("/", true)
.failureUrl("/login?error") // útil para diagnosticar
)
.rememberMe(rm -> rm
.key(keyRememberMe)
.rememberMeParameter("remember-me")
.rememberMeCookieName("IMPRIMELIBROS_REMEMBER")
.tokenValiditySeconds(60 * 60 * 24 * 2)
.userDetailsService(userDetailsService)
.tokenRepository(tokenRepo)
)
.logout(logout -> logout
.logoutUrl("/logout")
.logoutSuccessUrl("/")
.invalidateHttpSession(true)
.deleteCookies("JSESSIONID", "IMPRIMELIBROS_REMEMBER")
.permitAll()
);
return http.build();
}
}

View File

@ -12,68 +12,117 @@ import java.util.function.Function;
public class DataTable<T> {
public interface FilterHook<T> extends BiConsumer<SpecBuilder<T>, DataTablesRequest> {}
public interface SpecBuilder<T> { void add(Specification<T> extra); }
public interface FilterHook<T> extends BiConsumer<SpecBuilder<T>, DataTablesRequest> {
}
public interface SpecBuilder<T> {
void add(Specification<T> extra);
}
private final JpaSpecificationExecutor<T> repo;
private final Class<T> entityClass;
private final DataTablesRequest dt;
private final List<String> searchable;
private final List<Function<T, Map<String,Object>>> adders = new ArrayList<>();
private final List<Function<Map<String,Object>, Map<String,Object>>> editors = new ArrayList<>();
private final List<Function<T, Map<String, Object>>> adders = new ArrayList<>();
private final List<Function<Map<String, Object>, Map<String, Object>>> editors = new ArrayList<>();
private final List<FilterHook<T>> filters = new ArrayList<>();
private Specification<T> baseSpec = (root,q,cb) -> cb.conjunction();
private Specification<T> baseSpec = (root, q, cb) -> cb.conjunction();
private final ObjectMapper om = new ObjectMapper();
private DataTable(JpaSpecificationExecutor<T> repo, Class<T> entityClass, DataTablesRequest dt, List<String> searchable) {
this.repo = repo; this.entityClass = entityClass; this.dt = dt; this.searchable = searchable;
private DataTable(JpaSpecificationExecutor<T> repo, Class<T> entityClass, DataTablesRequest dt,
List<String> searchable) {
this.repo = repo;
this.entityClass = entityClass;
this.dt = dt;
this.searchable = searchable;
}
public static <T> DataTable<T> of(JpaSpecificationExecutor<T> repo, Class<T> entityClass, DataTablesRequest dt, List<String> searchable) {
public static <T> DataTable<T> of(JpaSpecificationExecutor<T> repo, Class<T> entityClass, DataTablesRequest dt,
List<String> searchable) {
return new DataTable<>(repo, entityClass, dt, searchable);
}
/** Equivalente a tu $q->where(...): establece condición base */
public DataTable<T> where(Specification<T> spec) { this.baseSpec = this.baseSpec.and(spec); return this; }
public DataTable<T> where(Specification<T> spec) {
this.baseSpec = this.baseSpec.and(spec);
return this;
}
/** add("campo", fn(entity)->valor|Map) */
public DataTable<T> add(String field, Function<T, Object> fn) {
adders.add(entity -> {
Map<String,Object> m = new HashMap<>();
Map<String, Object> m = new HashMap<>();
m.put(field, fn.apply(entity));
return m;
});
return this;
}
/** add(fn(entity)->Map<String,Object>) para devolver objetos anidados como tu "logo" */
public DataTable<T> add(Function<T, Map<String,Object>> fn) { adders.add(fn); return this; }
/**
* add(fn(entity)->Map<String,Object>) para devolver objetos anidados como tu
* "logo"
*/
public DataTable<T> add(Function<T, Map<String, Object>> fn) {
adders.add(fn);
return this;
}
/** edit("campo", fn(entity)->valor) sobreescribe un campo existente o lo crea si no existe */
/**
* edit("campo", fn(entity)->valor) sobreescribe un campo existente o lo crea si
* no existe
*/
public DataTable<T> edit(String field, Function<T, Object> fn) {
editors.add(row -> { row.put(field, fn.apply((T)row.get("__entity"))); return row; });
editors.add(row -> {
row.put(field, fn.apply((T) row.get("__entity")));
return row;
});
return this;
}
/** filter((builder, req) -> builder.add(miExtraSpec(req))) */
public DataTable<T> filter(FilterHook<T> hook) { filters.add(hook); return this; }
public DataTable<T> filter(FilterHook<T> hook) {
filters.add(hook);
return this;
}
public DataTablesResponse<Map<String,Object>> toJson(long totalCount) {
public DataTablesResponse<Map<String, Object>> toJson(long totalCount) {
// Construye spec con búsqueda global + base + filtros custom
Specification<T> spec = baseSpec.and(DataTablesSpecification.build(dt, searchable));
final Specification<T>[] holder = new Specification[]{ spec };
final Specification<T>[] holder = new Specification[] { spec };
filters.forEach(h -> h.accept(extra -> holder[0] = holder[0].and(extra), dt));
spec = holder[0];
// Sort
// Sort
Sort sort = Sort.unsorted();
if (!dt.order.isEmpty() && !dt.columns.isEmpty()) {
List<Sort.Order> orders = new ArrayList<>();
for (var o : dt.order) {
String field = dt.columns.get(o.column).name;
orders.add(new Sort.Order("desc".equalsIgnoreCase(o.dir) ? Sort.Direction.DESC : Sort.Direction.ASC, field));
var col = dt.columns.get(o.column);
String field = col != null ? col.name : null;
if (field == null || field.isBlank())
continue;
if (!col.orderable)
continue;
if (!searchable.contains(field))
continue; // << usa tu whitelist
orders.add(new Sort.Order(
"desc".equalsIgnoreCase(o.dir) ? Sort.Direction.DESC : Sort.Direction.ASC,
field));
}
if (!orders.isEmpty()) {
sort = Sort.by(orders);
} else {
for (var c : dt.columns) {
if (c != null && c.orderable && c.name != null && !c.name.isBlank()
&& searchable.contains(c.name)) {
sort = Sort.by(c.name);
break;
}
}
}
sort = Sort.by(orders);
}
// Page
@ -84,12 +133,14 @@ public class DataTable<T> {
long filtered = p.getTotalElements();
// Mapear entidad -> Map base (via Jackson) + add/edit
List<Map<String,Object>> data = new ArrayList<>();
List<Map<String, Object>> data = new ArrayList<>();
for (T e : p.getContent()) {
Map<String,Object> row = om.convertValue(e, Map.class);
Map<String, Object> row = om.convertValue(e, Map.class);
row.put("__entity", e); // para editores que necesiten la entidad
for (var ad : adders) row.putAll(ad.apply(e));
for (var ed : editors) ed.apply(row);
for (var ad : adders)
row.putAll(ad.apply(e));
for (var ed : editors)
ed.apply(row);
row.remove("__entity");
data.add(row);
}

View File

@ -12,10 +12,9 @@ public class DataTablesService {
public static <T> DataTablesResponse<T> handle(
DataTablesRequest dt,
JpaSpecificationExecutor<T> repo,
long totalCount, // count sin filtros (cacheable)
long totalCount, // count sin filtros (cacheable)
List<String> searchableFields,
Class<T> entityClass
) {
Class<T> entityClass) {
// Spec (filtros)
Specification<T> spec = DataTablesSpecification.build(dt, searchableFields);
@ -23,11 +22,37 @@ public class DataTablesService {
Sort sort = Sort.unsorted();
if (!dt.order.isEmpty() && !dt.columns.isEmpty()) {
List<Sort.Order> orders = new ArrayList<>();
for (DataTablesRequest.Order o : dt.order) {
String field = dt.columns.get(o.column).name;
orders.add(new Sort.Order("desc".equalsIgnoreCase(o.dir) ? Sort.Direction.DESC : Sort.Direction.ASC, field));
for (var o : dt.order) {
var col = dt.columns.get(o.column);
String field = col != null ? col.name : null;
// Acepta solo columnas válidas: no vacías, marcadas como orderable y en la
// whitelist "searchable"
if (field == null || field.isBlank())
continue;
if (!col.orderable)
continue;
if (!searchableFields.contains(field))
continue;
orders.add(new Sort.Order(
"desc".equalsIgnoreCase(o.dir) ? Sort.Direction.DESC : Sort.Direction.ASC,
field));
}
if (!orders.isEmpty()) {
sort = Sort.by(orders);
} else {
// Fallback: primera columna de dt.columns que sea orderable y esté en la
// whitelist
for (var c : dt.columns) {
if (c != null && c.orderable && c.name != null && !c.name.isBlank()
&& searchableFields.contains(c.name)) {
sort = Sort.by(c.name);
break;
}
}
// Si no hay ninguna válida, sort se queda UNSORTED
}
sort = Sort.by(orders);
}
// Page
@ -42,7 +67,6 @@ public class DataTablesService {
dt.draw,
totalCount,
filtered,
result.getContent()
);
result.getContent());
}
}

View File

@ -8,30 +8,42 @@ import java.util.List;
public class DataTablesSpecification {
/**
* Crea una Specification con búsqueda global y por columna (LIKE case-insensitive)
* @param dt request de datatables
* Crea una Specification con búsqueda global y por columna (LIKE
* case-insensitive)
*
* @param dt request de datatables
* @param searchableFields campos del entity para el buscador global
*/
public static <T> Specification<T> build(DataTablesRequest dt, List<String> searchableFields) {
return (root, query, cb) -> {
List<Predicate> ands = new ArrayList<>();
// Filtro por columna (si quieres soportarlo)
// Filtro por columna (si lo usas en el cliente)
for (int i = 0; i < dt.columns.size(); i++) {
DataTablesRequest.Column col = dt.columns.get(i);
if (col.searchable && col.search != null && col.search.value != null && !col.search.value.isEmpty()) {
ands.add(like(cb, root.get(col.name), col.search.value));
try {
ands.add(like(cb, root.get(col.name), col.search.value));
} catch (IllegalArgumentException ex) {
// columna no mapeada o relación: la ignoramos
}
}
}
// Búsqueda global
if (dt.search != null && dt.search.value != null && !dt.search.value.isEmpty() && !searchableFields.isEmpty()) {
if (dt.search != null && dt.search.value != null && !dt.search.value.isEmpty()
&& !searchableFields.isEmpty()) {
String term = "%" + dt.search.value.trim().toLowerCase() + "%";
List<Predicate> ors = new ArrayList<>();
for (String f : searchableFields) {
ors.add(cb.like(cb.lower(root.get(f).as(String.class)), term));
try {
ors.add(cb.like(cb.lower(root.get(f).as(String.class)), term));
} catch (IllegalArgumentException ex) {
// campo no simple: lo saltamos
}
}
ands.add(cb.or(ors.toArray(new Predicate[0])));
if (!ors.isEmpty())
ands.add(cb.or(ors.toArray(new Predicate[0])));
}
return ands.isEmpty() ? cb.conjunction() : cb.and(ands.toArray(new Predicate[0]));

View File

@ -4,43 +4,79 @@ import com.imprimelibros.erp.datatables.DataTablesResponse;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.context.MessageSource;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import com.imprimelibros.erp.datatables.DataTablesRequest;
import com.imprimelibros.erp.datatables.DataTablesParser;
import com.imprimelibros.erp.datatables.DataTable;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.List;
import java.util.Locale;
@Controller
@PreAuthorize("hasRole('ADMIN') or hasRole('SUPERADMIN')")
@RequestMapping("/users")
public class UserController {
public class UserController {
private UserDao repo;
private MessageSource messageSource;
public UserController(UserDao repo, UserService userService) {
public UserController(UserDao repo, UserService userService, MessageSource messageSource) {
this.repo = repo;
this.messageSource = messageSource;
}
@PreAuthorize("hasRole('ADMIN') or hasRole('SUPERADMIN')")
@GetMapping("/")
public DataTablesResponse<Map<String,Object>> datatable(HttpServletRequest request) {
DataTablesRequest dt = DataTablesParser.from(request);
@GetMapping
public String list(Model model, Authentication authentication, Locale locale) {
return "imprimelibros/users/users-list";
}
// IMPORTANTE: asegúrate de que el controller es @RestController O anota el
// método con @ResponseBody.
@GetMapping(value = "/datatable", produces = "application/json")
@ResponseBody
public DataTablesResponse<Map<String, Object>> datatable(HttpServletRequest request, Locale locale) {
DataTablesRequest dt = DataTablesParser.from(request); //
// OJO: en la whitelist mete solo columnas "reales" y escalares (no relaciones).
// Si 'role' es relación, sácalo de aquí:
List<String> whitelist = List.of("fullName", "userName", "enabled");
Specification<User> base = (root, query, cb) -> cb.conjunction();
long total = repo.count();
return DataTable
.of(repo, User.class, dt, List.of(
"username", "email", "role" // campos buscables
))
.where(base)
.toJson(total);
.of(repo, User.class, dt, whitelist) // 'searchable' en DataTable.java
.edit("enabled", (User u) -> {
if (u.isEnabled()) {
return "<span class=\"badge bg-success\" >" + messageSource.getMessage("usuarios.tabla.activo", null, locale) + "</span>";
} else {
return "<span class=\"badge bg-danger\" >" + messageSource.getMessage("usuarios.tabla.inactivo", null, locale) + "</span>";
}
})
// si 'role' es relación, crea una columna calculada “segura”:
// acciones virtuales:
.add("roles", (User u) -> u.getRoles().stream().map(Role::getName).collect(Collectors.joining(", ")))
.add("actions", (user) -> {
return "<div class=\"hstack gap-3 flex-wrap\">\n" +
" <a href=\"/users/" + user.getId() + "\" class=\"link-success fs-15\"><i class=\"ri-edit-2-line\"></i></a>\n" +
" <a href=\"javascript:void(0);\" data-id=\"" + user.getId() + "\" class=\"link-danger fs-15\"><i class=\"user-delete ri-delete-bin-line\"></i></a>\n" +
" </div>";
})
.where(base)
.toJson(total);
}
}

View File

@ -11,4 +11,6 @@ login.slogan=imprimelibros.com<br>Especialistas en impresión de libros
login.email-placeholder=Introduce tu correo electrónico
login.password-placeholder=Introduce tu contraseña
login.new-account=¿No tienes una cuenta?
login.sign-up=Regístrate
login.sign-up=Regístrate
login.error=Credenciales inválidas

View File

@ -0,0 +1 @@

View File

@ -0,0 +1,10 @@
usuarios.titulo=Usuarios
usuarios.nuevo=Nuevo usuario
usuarios.tabla.nombre=Nombre
usuarios.tabla.email=Correo electrónico
usuarios.tabla.rol=Rol
usuarios.tabla.estado=Estado
usuarios.tabla.acciones=Acciones
usuarios.tabla.activo=Activo
usuarios.tabla.inactivo=Inactivo

View File

@ -1,7 +1,7 @@
(function () {
"use strict";
const DEFAULT_LANG = "es";
const DEFAULT_LANG = "es-ES";
function getCurrentLang() {
// Viene del servidor (Thymeleaf): <html th:lang="${#locale.language}">
@ -11,7 +11,7 @@
function setFlag(lang) {
const img = document.getElementById("header-lang-img");
if (!img) return;
img.src = (lang === "en")
img.src = (lang === "en-GB")
? "/assets/images/flags/gb.svg"
: "/assets/images/flags/spain.svg";
}

View File

@ -1,7 +1,9 @@
window.languageBundle.get = function (key, ...params) {
let text = this[key] || key;
params.forEach((val, i) => {
text = text.replace(`{${i}}`, val);
});
return text;
if (window.languageBundle) {
window.languageBundle.get = function (key, ...params) {
let text = this[key] || key;
params.forEach((val, i) => {
text = text.replace(`{${i}}`, val);
});
return text;
}
};

View File

@ -0,0 +1,29 @@
$(() => {
const language = document.documentElement.lang || 'es-ES';
const table = new DataTable('#users-datatable', {
processing: true,
serverSide: true,
language: {
url: '/assets/libs/datatables/i18n/' + language + '.json'
},
responsive: true,
ajax: {
url: '/users/datatable',
method: 'GET',
data: d => { /* extra params si quieres */ }
},
order: [[0, 'asc']],
columns: [
{ data: 'fullName', name: 'fullname' },
{ data: 'userName', name: 'username' },
{ data: 'roles', name: 'roles' },
{ data: 'enabled', name: 'enabled', searchable: false },
{ data: 'actions', name: 'actions' }
],
columnDefs: [
// Desactiva orden y búsqueda en la columna de acciones
{ targets: -1, orderable: false, searchable: false }
]
});
});

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,4 @@
/*! DataTables Bootstrap 5 integration
* © SpryMedia Ltd - datatables.net/license
*/
!function(n){var o,a;"function"==typeof define&&define.amd?define(["jquery","datatables.net"],function(e){return n(e,window,document)}):"object"==typeof exports?(o=require("jquery"),a=function(e,t){t.fn.dataTable||require("datatables.net")(e,t)},"undefined"==typeof window?module.exports=function(e,t){return e=e||window,t=t||o(e),a(e,t),n(t,0,e.document)}:(a(window,o),module.exports=n(o,window,window.document))):n(jQuery,window,document)}(function(d,e,t){"use strict";var n=d.fn.dataTable;return d.extend(!0,n.defaults,{renderer:"bootstrap"}),d.extend(!0,n.ext.classes,{container:"dt-container dt-bootstrap5",search:{input:"form-control form-control-sm"},length:{select:"form-select form-select-sm"},processing:{container:"dt-processing card"}}),n.ext.renderer.pagingButton.bootstrap=function(e,t,n,o,a){var r=["dt-paging-button","page-item"],o=(o&&r.push("active"),a&&r.push("disabled"),d("<li>").addClass(r.join(" ")));return{display:o,clicker:d("<a>",{href:a?null:"#",class:"page-link"}).html(n).appendTo(o)}},n.ext.renderer.pagingContainer.bootstrap=function(e,t){return d("<ul/>").addClass("pagination").append(t)},n.ext.renderer.layout.bootstrap=function(e,t,n){var o=d("<div/>",{class:n.full?"row mt-2 justify-content-md-center":"row mt-2 justify-content-between"}).appendTo(t);d.each(n,function(e,t){e=t.table?"col-12":"start"===e?"col-md-auto me-auto":"end"===e?"col-md-auto ms-auto":"col-md";d("<div/>",{id:t.id||null,class:e+" "+(t.className||"")}).append(t.contents).appendTo(o)})},n});

View File

@ -0,0 +1,624 @@
/*
* This combined file was created by the DataTables downloader builder:
* https://datatables.net/download
*
* To rebuild or modify this file with the latest versions of the included
* software please visit:
* https://datatables.net/download/#bs5/jq-3.7.0/dt-2.3.4
*
* Included libraries:
* jQuery 3.7.0, DataTables 2.3.4
*/
:root {
--dt-row-selected: 13, 110, 253;
--dt-row-selected-text: 255, 255, 255;
--dt-row-selected-link: 228, 228, 228;
--dt-row-stripe: 0, 0, 0;
--dt-row-hover: 0, 0, 0;
--dt-column-ordering: 0, 0, 0;
--dt-header-align-items: center;
--dt-header-vertical-align: middle;
--dt-html-background: white;
}
:root.dark {
--dt-html-background: rgb(33, 37, 41);
}
table.dataTable tbody td.dt-control {
text-align: center;
cursor: pointer;
}
table.dataTable tbody td.dt-control:before {
display: inline-block;
box-sizing: border-box;
content: "";
border-top: 5px solid transparent;
border-left: 10px solid rgba(0, 0, 0, 0.5);
border-bottom: 5px solid transparent;
border-right: 0px solid transparent;
}
table.dataTable tbody tr.dt-hasChild td.dt-control:before {
border-top: 10px solid rgba(0, 0, 0, 0.5);
border-left: 5px solid transparent;
border-bottom: 0px solid transparent;
border-right: 5px solid transparent;
}
table.dataTable tfoot:empty {
display: none;
}
html.dark table.dataTable td.dt-control:before,
:root[data-bs-theme=dark] table.dataTable td.dt-control:before,
:root[data-theme=dark] table.dataTable td.dt-control:before {
border-left-color: rgba(255, 255, 255, 0.5);
}
html.dark table.dataTable tr.dt-hasChild td.dt-control:before,
:root[data-bs-theme=dark] table.dataTable tr.dt-hasChild td.dt-control:before,
:root[data-theme=dark] table.dataTable tr.dt-hasChild td.dt-control:before {
border-top-color: rgba(255, 255, 255, 0.5);
border-left-color: transparent;
}
div.dt-scroll {
width: 100%;
}
div.dt-scroll-body thead tr,
div.dt-scroll-body tfoot tr {
height: 0;
}
div.dt-scroll-body thead tr th, div.dt-scroll-body thead tr td,
div.dt-scroll-body tfoot tr th,
div.dt-scroll-body tfoot tr td {
height: 0 !important;
padding-top: 0px !important;
padding-bottom: 0px !important;
border-top-width: 0px !important;
border-bottom-width: 0px !important;
}
div.dt-scroll-body thead tr th div.dt-scroll-sizing, div.dt-scroll-body thead tr td div.dt-scroll-sizing,
div.dt-scroll-body tfoot tr th div.dt-scroll-sizing,
div.dt-scroll-body tfoot tr td div.dt-scroll-sizing {
height: 0 !important;
overflow: hidden !important;
}
table.dataTable thead > tr > th:active,
table.dataTable thead > tr > td:active {
outline: none;
}
table.dataTable thead > tr > th.dt-orderable-asc span.dt-column-order:before, table.dataTable thead > tr > th.dt-ordering-asc span.dt-column-order:before,
table.dataTable thead > tr > td.dt-orderable-asc span.dt-column-order:before,
table.dataTable thead > tr > td.dt-ordering-asc span.dt-column-order:before {
position: absolute;
display: block;
bottom: 50%;
content: "\25B2";
content: "\25B2"/"";
}
table.dataTable thead > tr > th.dt-orderable-desc span.dt-column-order:after, table.dataTable thead > tr > th.dt-ordering-desc span.dt-column-order:after,
table.dataTable thead > tr > td.dt-orderable-desc span.dt-column-order:after,
table.dataTable thead > tr > td.dt-ordering-desc span.dt-column-order:after {
position: absolute;
display: block;
top: 50%;
content: "\25BC";
content: "\25BC"/"";
}
table.dataTable thead > tr > th.dt-orderable-asc span.dt-column-order, table.dataTable thead > tr > th.dt-orderable-desc span.dt-column-order, table.dataTable thead > tr > th.dt-ordering-asc span.dt-column-order, table.dataTable thead > tr > th.dt-ordering-desc span.dt-column-order,
table.dataTable thead > tr > td.dt-orderable-asc span.dt-column-order,
table.dataTable thead > tr > td.dt-orderable-desc span.dt-column-order,
table.dataTable thead > tr > td.dt-ordering-asc span.dt-column-order,
table.dataTable thead > tr > td.dt-ordering-desc span.dt-column-order {
position: relative;
width: 12px;
height: 24px;
}
table.dataTable thead > tr > th.dt-orderable-asc span.dt-column-order:before, table.dataTable thead > tr > th.dt-orderable-asc span.dt-column-order:after, table.dataTable thead > tr > th.dt-orderable-desc span.dt-column-order:before, table.dataTable thead > tr > th.dt-orderable-desc span.dt-column-order:after, table.dataTable thead > tr > th.dt-ordering-asc span.dt-column-order:before, table.dataTable thead > tr > th.dt-ordering-asc span.dt-column-order:after, table.dataTable thead > tr > th.dt-ordering-desc span.dt-column-order:before, table.dataTable thead > tr > th.dt-ordering-desc span.dt-column-order:after,
table.dataTable thead > tr > td.dt-orderable-asc span.dt-column-order:before,
table.dataTable thead > tr > td.dt-orderable-asc span.dt-column-order:after,
table.dataTable thead > tr > td.dt-orderable-desc span.dt-column-order:before,
table.dataTable thead > tr > td.dt-orderable-desc span.dt-column-order:after,
table.dataTable thead > tr > td.dt-ordering-asc span.dt-column-order:before,
table.dataTable thead > tr > td.dt-ordering-asc span.dt-column-order:after,
table.dataTable thead > tr > td.dt-ordering-desc span.dt-column-order:before,
table.dataTable thead > tr > td.dt-ordering-desc span.dt-column-order:after {
left: 0;
opacity: 0.125;
line-height: 9px;
font-size: 0.8em;
}
table.dataTable thead > tr > th.dt-orderable-asc, table.dataTable thead > tr > th.dt-orderable-desc,
table.dataTable thead > tr > td.dt-orderable-asc,
table.dataTable thead > tr > td.dt-orderable-desc {
cursor: pointer;
}
table.dataTable thead > tr > th.dt-orderable-asc:hover, table.dataTable thead > tr > th.dt-orderable-desc:hover,
table.dataTable thead > tr > td.dt-orderable-asc:hover,
table.dataTable thead > tr > td.dt-orderable-desc:hover {
outline: 2px solid rgba(0, 0, 0, 0.05);
outline-offset: -2px;
}
table.dataTable thead > tr > th.dt-ordering-asc span.dt-column-order:before, table.dataTable thead > tr > th.dt-ordering-desc span.dt-column-order:after,
table.dataTable thead > tr > td.dt-ordering-asc span.dt-column-order:before,
table.dataTable thead > tr > td.dt-ordering-desc span.dt-column-order:after {
opacity: 0.6;
}
table.dataTable thead > tr > th.dt-orderable-none:not(.dt-ordering-asc, .dt-ordering-desc) span.dt-column-order:empty, table.dataTable thead > tr > th.sorting_desc_disabled span.dt-column-order:after, table.dataTable thead > tr > th.sorting_asc_disabled span.dt-column-order:before,
table.dataTable thead > tr > td.dt-orderable-none:not(.dt-ordering-asc, .dt-ordering-desc) span.dt-column-order:empty,
table.dataTable thead > tr > td.sorting_desc_disabled span.dt-column-order:after,
table.dataTable thead > tr > td.sorting_asc_disabled span.dt-column-order:before {
display: none;
}
table.dataTable thead > tr > th:active,
table.dataTable thead > tr > td:active {
outline: none;
}
table.dataTable thead > tr > th div.dt-column-header,
table.dataTable thead > tr > th div.dt-column-footer,
table.dataTable thead > tr > td div.dt-column-header,
table.dataTable thead > tr > td div.dt-column-footer,
table.dataTable tfoot > tr > th div.dt-column-header,
table.dataTable tfoot > tr > th div.dt-column-footer,
table.dataTable tfoot > tr > td div.dt-column-header,
table.dataTable tfoot > tr > td div.dt-column-footer {
display: flex;
justify-content: space-between;
align-items: var(--dt-header-align-items);
gap: 4px;
}
table.dataTable thead > tr > th div.dt-column-header span.dt-column-title,
table.dataTable thead > tr > th div.dt-column-footer span.dt-column-title,
table.dataTable thead > tr > td div.dt-column-header span.dt-column-title,
table.dataTable thead > tr > td div.dt-column-footer span.dt-column-title,
table.dataTable tfoot > tr > th div.dt-column-header span.dt-column-title,
table.dataTable tfoot > tr > th div.dt-column-footer span.dt-column-title,
table.dataTable tfoot > tr > td div.dt-column-header span.dt-column-title,
table.dataTable tfoot > tr > td div.dt-column-footer span.dt-column-title {
flex-grow: 1;
}
table.dataTable thead > tr > th div.dt-column-header span.dt-column-title:empty,
table.dataTable thead > tr > th div.dt-column-footer span.dt-column-title:empty,
table.dataTable thead > tr > td div.dt-column-header span.dt-column-title:empty,
table.dataTable thead > tr > td div.dt-column-footer span.dt-column-title:empty,
table.dataTable tfoot > tr > th div.dt-column-header span.dt-column-title:empty,
table.dataTable tfoot > tr > th div.dt-column-footer span.dt-column-title:empty,
table.dataTable tfoot > tr > td div.dt-column-header span.dt-column-title:empty,
table.dataTable tfoot > tr > td div.dt-column-footer span.dt-column-title:empty {
display: none;
}
div.dt-scroll-body > table.dataTable > thead > tr > th,
div.dt-scroll-body > table.dataTable > thead > tr > td {
overflow: hidden;
}
:root.dark table.dataTable thead > tr > th.dt-orderable-asc:hover, :root.dark table.dataTable thead > tr > th.dt-orderable-desc:hover,
:root.dark table.dataTable thead > tr > td.dt-orderable-asc:hover,
:root.dark table.dataTable thead > tr > td.dt-orderable-desc:hover,
:root[data-bs-theme=dark] table.dataTable thead > tr > th.dt-orderable-asc:hover,
:root[data-bs-theme=dark] table.dataTable thead > tr > th.dt-orderable-desc:hover,
:root[data-bs-theme=dark] table.dataTable thead > tr > td.dt-orderable-asc:hover,
:root[data-bs-theme=dark] table.dataTable thead > tr > td.dt-orderable-desc:hover {
outline: 2px solid rgba(255, 255, 255, 0.05);
}
div.dt-processing {
position: absolute;
top: 50%;
left: 50%;
width: 200px;
margin-left: -100px;
margin-top: -22px;
text-align: center;
padding: 2px;
z-index: 10;
}
div.dt-processing > div:last-child {
position: relative;
width: 80px;
height: 15px;
margin: 1em auto;
}
div.dt-processing > div:last-child > div {
position: absolute;
top: 0;
width: 13px;
height: 13px;
border-radius: 50%;
background: rgb(13, 110, 253);
background: rgb(var(--dt-row-selected));
animation-timing-function: cubic-bezier(0, 1, 1, 0);
}
div.dt-processing > div:last-child > div:nth-child(1) {
left: 8px;
animation: datatables-loader-1 0.6s infinite;
}
div.dt-processing > div:last-child > div:nth-child(2) {
left: 8px;
animation: datatables-loader-2 0.6s infinite;
}
div.dt-processing > div:last-child > div:nth-child(3) {
left: 32px;
animation: datatables-loader-2 0.6s infinite;
}
div.dt-processing > div:last-child > div:nth-child(4) {
left: 56px;
animation: datatables-loader-3 0.6s infinite;
}
@keyframes datatables-loader-1 {
0% {
transform: scale(0);
}
100% {
transform: scale(1);
}
}
@keyframes datatables-loader-3 {
0% {
transform: scale(1);
}
100% {
transform: scale(0);
}
}
@keyframes datatables-loader-2 {
0% {
transform: translate(0, 0);
}
100% {
transform: translate(24px, 0);
}
}
table.dataTable.nowrap th, table.dataTable.nowrap td {
white-space: nowrap;
}
table.dataTable th,
table.dataTable td {
box-sizing: border-box;
}
table.dataTable th.dt-type-numeric, table.dataTable th.dt-type-date,
table.dataTable td.dt-type-numeric,
table.dataTable td.dt-type-date {
text-align: right;
}
table.dataTable th.dt-type-numeric div.dt-column-header,
table.dataTable th.dt-type-numeric div.dt-column-footer, table.dataTable th.dt-type-date div.dt-column-header,
table.dataTable th.dt-type-date div.dt-column-footer,
table.dataTable td.dt-type-numeric div.dt-column-header,
table.dataTable td.dt-type-numeric div.dt-column-footer,
table.dataTable td.dt-type-date div.dt-column-header,
table.dataTable td.dt-type-date div.dt-column-footer {
flex-direction: row-reverse;
}
table.dataTable th.dt-left,
table.dataTable td.dt-left {
text-align: left;
}
table.dataTable th.dt-left div.dt-column-header,
table.dataTable th.dt-left div.dt-column-footer,
table.dataTable td.dt-left div.dt-column-header,
table.dataTable td.dt-left div.dt-column-footer {
flex-direction: row;
}
table.dataTable th.dt-center,
table.dataTable td.dt-center {
text-align: center;
}
table.dataTable th.dt-right,
table.dataTable td.dt-right {
text-align: right;
}
table.dataTable th.dt-right div.dt-column-header,
table.dataTable th.dt-right div.dt-column-footer,
table.dataTable td.dt-right div.dt-column-header,
table.dataTable td.dt-right div.dt-column-footer {
flex-direction: row-reverse;
}
table.dataTable th.dt-justify,
table.dataTable td.dt-justify {
text-align: justify;
}
table.dataTable th.dt-justify div.dt-column-header,
table.dataTable th.dt-justify div.dt-column-footer,
table.dataTable td.dt-justify div.dt-column-header,
table.dataTable td.dt-justify div.dt-column-footer {
flex-direction: row;
}
table.dataTable th.dt-nowrap,
table.dataTable td.dt-nowrap {
white-space: nowrap;
}
table.dataTable th.dt-empty,
table.dataTable td.dt-empty {
text-align: center;
vertical-align: top;
}
table.dataTable thead th,
table.dataTable thead td,
table.dataTable tfoot th,
table.dataTable tfoot td {
text-align: left;
vertical-align: var(--dt-header-vertical-align);
}
table.dataTable thead th.dt-head-left,
table.dataTable thead td.dt-head-left,
table.dataTable tfoot th.dt-head-left,
table.dataTable tfoot td.dt-head-left {
text-align: left;
}
table.dataTable thead th.dt-head-left div.dt-column-header,
table.dataTable thead th.dt-head-left div.dt-column-footer,
table.dataTable thead td.dt-head-left div.dt-column-header,
table.dataTable thead td.dt-head-left div.dt-column-footer,
table.dataTable tfoot th.dt-head-left div.dt-column-header,
table.dataTable tfoot th.dt-head-left div.dt-column-footer,
table.dataTable tfoot td.dt-head-left div.dt-column-header,
table.dataTable tfoot td.dt-head-left div.dt-column-footer {
flex-direction: row;
}
table.dataTable thead th.dt-head-center,
table.dataTable thead td.dt-head-center,
table.dataTable tfoot th.dt-head-center,
table.dataTable tfoot td.dt-head-center {
text-align: center;
}
table.dataTable thead th.dt-head-right,
table.dataTable thead td.dt-head-right,
table.dataTable tfoot th.dt-head-right,
table.dataTable tfoot td.dt-head-right {
text-align: right;
}
table.dataTable thead th.dt-head-right div.dt-column-header,
table.dataTable thead th.dt-head-right div.dt-column-footer,
table.dataTable thead td.dt-head-right div.dt-column-header,
table.dataTable thead td.dt-head-right div.dt-column-footer,
table.dataTable tfoot th.dt-head-right div.dt-column-header,
table.dataTable tfoot th.dt-head-right div.dt-column-footer,
table.dataTable tfoot td.dt-head-right div.dt-column-header,
table.dataTable tfoot td.dt-head-right div.dt-column-footer {
flex-direction: row-reverse;
}
table.dataTable thead th.dt-head-justify,
table.dataTable thead td.dt-head-justify,
table.dataTable tfoot th.dt-head-justify,
table.dataTable tfoot td.dt-head-justify {
text-align: justify;
}
table.dataTable thead th.dt-head-justify div.dt-column-header,
table.dataTable thead th.dt-head-justify div.dt-column-footer,
table.dataTable thead td.dt-head-justify div.dt-column-header,
table.dataTable thead td.dt-head-justify div.dt-column-footer,
table.dataTable tfoot th.dt-head-justify div.dt-column-header,
table.dataTable tfoot th.dt-head-justify div.dt-column-footer,
table.dataTable tfoot td.dt-head-justify div.dt-column-header,
table.dataTable tfoot td.dt-head-justify div.dt-column-footer {
flex-direction: row;
}
table.dataTable thead th.dt-head-nowrap,
table.dataTable thead td.dt-head-nowrap,
table.dataTable tfoot th.dt-head-nowrap,
table.dataTable tfoot td.dt-head-nowrap {
white-space: nowrap;
}
table.dataTable tbody th.dt-body-left,
table.dataTable tbody td.dt-body-left {
text-align: left;
}
table.dataTable tbody th.dt-body-center,
table.dataTable tbody td.dt-body-center {
text-align: center;
}
table.dataTable tbody th.dt-body-right,
table.dataTable tbody td.dt-body-right {
text-align: right;
}
table.dataTable tbody th.dt-body-justify,
table.dataTable tbody td.dt-body-justify {
text-align: justify;
}
table.dataTable tbody th.dt-body-nowrap,
table.dataTable tbody td.dt-body-nowrap {
white-space: nowrap;
}
/*! Bootstrap 5 integration for DataTables
*
* ©2020 SpryMedia Ltd, all rights reserved.
* License: MIT datatables.net/license/mit
*/
table.table.dataTable {
clear: both;
margin-bottom: 0;
max-width: none;
border-spacing: 0;
}
table.table.dataTable.table-striped > tbody > tr:nth-of-type(2n+1) > * {
box-shadow: none;
}
table.table.dataTable > :not(caption) > * > * {
background-color: var(--bs-table-bg);
}
table.table.dataTable > tbody > tr {
background-color: transparent;
}
table.table.dataTable > tbody > tr.selected > * {
box-shadow: inset 0 0 0 9999px rgb(13, 110, 253);
box-shadow: inset 0 0 0 9999px rgb(var(--dt-row-selected));
color: rgb(255, 255, 255);
color: rgb(var(--dt-row-selected-text));
}
table.table.dataTable > tbody > tr.selected a {
color: rgb(228, 228, 228);
color: rgb(var(--dt-row-selected-link));
}
table.table.dataTable.table-striped > tbody > tr:nth-of-type(2n+1) > * {
box-shadow: inset 0 0 0 9999px rgba(var(--dt-row-stripe), 0.05);
}
table.table.dataTable.table-striped > tbody > tr:nth-of-type(2n+1).selected > * {
box-shadow: inset 0 0 0 9999px rgba(13, 110, 253, 0.95);
box-shadow: inset 0 0 0 9999px rgba(var(--dt-row-selected), 0.95);
}
table.table.dataTable.table-hover > tbody > tr:hover > * {
box-shadow: inset 0 0 0 9999px rgba(var(--dt-row-hover), 0.075);
}
table.table.dataTable.table-hover > tbody > tr.selected:hover > * {
box-shadow: inset 0 0 0 9999px rgba(13, 110, 253, 0.975);
box-shadow: inset 0 0 0 9999px rgba(var(--dt-row-selected), 0.975);
}
div.dt-container div.dt-layout-start > *:not(:last-child) {
margin-right: 1em;
}
div.dt-container div.dt-layout-end > *:not(:first-child) {
margin-left: 1em;
}
div.dt-container div.dt-layout-full {
width: 100%;
}
div.dt-container div.dt-layout-full > *:only-child {
margin-left: auto;
margin-right: auto;
}
div.dt-container div.dt-layout-table > div {
display: block !important;
}
@media screen and (max-width: 767px) {
div.dt-container div.dt-layout-start > *:not(:last-child) {
margin-right: 0;
}
div.dt-container div.dt-layout-end > *:not(:first-child) {
margin-left: 0;
}
}
div.dt-container {
position: relative;
}
div.dt-container div.dt-length label {
font-weight: normal;
text-align: left;
white-space: nowrap;
}
div.dt-container div.dt-length select {
width: auto;
display: inline-block;
margin-right: 0.5em;
}
div.dt-container div.dt-search {
text-align: right;
}
div.dt-container div.dt-search label {
font-weight: normal;
white-space: nowrap;
text-align: left;
}
div.dt-container div.dt-search input {
margin-left: 0.5em;
display: inline-block;
width: auto;
}
div.dt-container div.dt-paging {
margin: 0;
}
div.dt-container div.dt-paging ul.pagination {
margin: 2px 0;
flex-wrap: wrap;
}
div.dt-container div.dt-row {
position: relative;
}
div.dt-scroll-head table.dataTable {
margin-bottom: 0 !important;
}
div.dt-scroll-body {
border-bottom-color: var(--bs-border-color);
border-bottom-width: var(--bs-border-width);
border-bottom-style: solid;
}
div.dt-scroll-body > table {
border-top: none;
margin-top: 0 !important;
margin-bottom: 0 !important;
}
div.dt-scroll-body > table > tbody > tr:first-child {
border-top-width: 0;
}
div.dt-scroll-body > table > thead > tr {
border-width: 0 !important;
}
div.dt-scroll-body > table > tbody > tr:last-child > * {
border-bottom: none;
}
div.dt-scroll-foot > .dt-scroll-footInner {
box-sizing: content-box;
}
div.dt-scroll-foot > .dt-scroll-footInner > table {
margin-top: 0 !important;
border-top: none;
}
div.dt-scroll-foot > .dt-scroll-footInner > table > tfoot > tr:first-child {
border-top-width: 0 !important;
}
@media screen and (max-width: 767px) {
div.dt-container div.dt-length,
div.dt-container div.dt-search,
div.dt-container div.dt-info,
div.dt-container div.dt-paging {
text-align: center;
}
div.dt-container .row {
--bs-gutter-y: 0.5rem;
}
div.dt-container div.dt-paging ul.pagination {
justify-content: center !important;
}
}
table.dataTable.table-sm > thead > tr th.dt-orderable-asc, table.dataTable.table-sm > thead > tr th.dt-orderable-desc, table.dataTable.table-sm > thead > tr th.dt-ordering-asc, table.dataTable.table-sm > thead > tr th.dt-ordering-desc,
table.dataTable.table-sm > thead > tr td.dt-orderable-asc,
table.dataTable.table-sm > thead > tr td.dt-orderable-desc,
table.dataTable.table-sm > thead > tr td.dt-ordering-asc,
table.dataTable.table-sm > thead > tr td.dt-ordering-desc {
padding-right: 0.25rem;
}
table.dataTable.table-sm > thead > tr th.dt-orderable-asc span.dt-column-order, table.dataTable.table-sm > thead > tr th.dt-orderable-desc span.dt-column-order, table.dataTable.table-sm > thead > tr th.dt-ordering-asc span.dt-column-order, table.dataTable.table-sm > thead > tr th.dt-ordering-desc span.dt-column-order,
table.dataTable.table-sm > thead > tr td.dt-orderable-asc span.dt-column-order,
table.dataTable.table-sm > thead > tr td.dt-orderable-desc span.dt-column-order,
table.dataTable.table-sm > thead > tr td.dt-ordering-asc span.dt-column-order,
table.dataTable.table-sm > thead > tr td.dt-ordering-desc span.dt-column-order {
right: 0.25rem;
}
table.dataTable.table-sm > thead > tr th.dt-type-date span.dt-column-order, table.dataTable.table-sm > thead > tr th.dt-type-numeric span.dt-column-order,
table.dataTable.table-sm > thead > tr td.dt-type-date span.dt-column-order,
table.dataTable.table-sm > thead > tr td.dt-type-numeric span.dt-column-order {
left: 0.25rem;
}
div.dt-scroll-head table.table-bordered {
border-bottom-width: 0;
}
div.table-responsive > div.dt-container > div.row {
margin: 0;
}
div.table-responsive > div.dt-container > div.row > div[class^=col-]:first-child {
padding-left: 0;
}
div.table-responsive > div.dt-container > div.row > div[class^=col-]:last-child {
padding-right: 0;
}
:root[data-bs-theme=dark] {
--dt-row-hover: 255, 255, 255;
--dt-row-stripe: 255, 255, 255;
--dt-column-ordering: 255, 255, 255;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,275 @@
{
"aria": {
"paginate": {
"first": "Erste",
"last": "Letzte",
"next": "Nächste",
"previous": "Vorherige"
}
},
"autoFill": {
"cancel": "Abbrechen",
"fill": "Alle Zellen mit <i>%d<i> füllen<\/i><\/i>",
"fillHorizontal": "Alle horizontalen Zellen füllen",
"fillVertical": "Alle vertikalen Zellen füllen",
"info": ""
},
"buttons": {
"collection": "Aktionen <span class=\"ui-button-icon-primary ui-icon ui-icon-triangle-1-s\"><\/span>",
"colvis": "Spaltensichtbarkeit",
"colvisRestore": "Sichtbarkeit wiederherstellen",
"copy": "Kopieren",
"copyKeys": "Taste <i>STRG&lt;\\\/i&gt; oder <i>⌘&lt;\\\/i&gt; + <i>C&lt;\\\/i&gt; drücken um die Tabelle<br \/>in den Zwischenspeicher zu kopieren.<br \/><br \/>Um den Vorgang abzubrechen, Nachricht anklicken oder Escape-Taste drücken.<\/i><\/i><\/i>",
"copySuccess": {
"_": "%d Zeilen kopiert",
"1": "1 Zeile kopiert"
},
"copyTitle": "In Zwischenablage kopieren",
"createState": "Ansicht erstellen",
"csv": "CSV",
"excel": "Excel",
"pageLength": {
"_": "Zeige %d Zeilen",
"-1": "Alle Zeilen anzeigen",
"1": "Zeigt 1 Zeile"
},
"pdf": "PDF",
"print": "Drucken",
"removeAllStates": "Alle Ansichten entfernen",
"removeState": "Entfernen",
"renameState": "Umbenennen",
"savedStates": "Gespeicherte Ansicht",
"stateRestore": "Ansicht %d",
"updateState": "Aktualisieren"
},
"columnControl": {
"colVis": "Sichtbarkeit der Spalte",
"colVisDropdown": "Sichtbarkeit der Spalte",
"dropdown": "Mehr...",
"list": {
"all": "Alle auswählen",
"none": "Nichts auswählen",
"search": "Suche..."
},
"orderAddAsc": "Aufsteigende Sortierung hinzufügen",
"orderAddDesc": "Absteigende Sortierung hinzufügen",
"orderAsc": "Aufsteigend sortieren",
"orderDesc": "Absteigend sortieren",
"orderRemove": "Aus Sortierung löschen",
"reorder": "Spalten neu sortieren",
"reorderLeft": "Spalte nach links verschieben",
"reorderRight": "Spalte nach rechts verschieben",
"searchClear": "Suche leeren",
"searchDropdown": "Suchen"
},
"datetime": {
"amPm": {
"0": "Vormittag",
"1": "Nachmittag"
},
"hours": "Stunden",
"minutes": "Minuten",
"months": {
"0": "Januar",
"1": "Februar",
"10": "November",
"11": "Dezember",
"2": "März",
"3": "April",
"4": "Mai",
"5": "Juni",
"6": "Juli",
"7": "August",
"8": "September",
"9": "Oktober"
},
"next": "Nachher",
"previous": "Vorher",
"seconds": "Sekunden",
"unknown": "Unbekannt",
"weekdays": {
"0": "Sonntag",
"1": "Montag",
"2": "Dienstag",
"3": "Mittwoch",
"4": "Donnerstag",
"5": "Freitag",
"6": "Samstag"
}
},
"decimal": "",
"editor": {
"close": "Schließen",
"create": {
"button": "Neu",
"submit": "Erstellen",
"title": "Neuen Eintrag erstellen"
},
"edit": {
"button": "Bearbeiten",
"submit": "Bearbeiten",
"title": "Eintrag bearbeiten"
},
"error": {
"system": "Ein Systemfehler ist aufgetreten"
},
"multi": {
"info": "Die ausgewählten Elemente enthalten mehrere Werte für dieses Feld. Um alle Elemente für dieses Feld zu bearbeiten und auf denselben Wert zu setzen, hier klicken oder tippen, andernfalls behalten diese ihre individuellen Werte bei.",
"noMulti": "Dieses Feld kann nur einzeln bearbeitet werden, nicht als Teil einer Mengen-Änderung.",
"restore": "Änderungen zurücksetzen",
"title": "Mehrere Werte"
},
"remove": {
"button": "Entfernen",
"confirm": {
"_": "Sollen %d Zeilen gelöscht werden?",
"1": "Soll diese Zeile gelöscht werden?"
},
"submit": "Entfernen",
"title": "Entfernen"
}
},
"emptyTable": "Keine Daten in der Tabelle vorhanden",
"info": "_START_ bis _END_ von _TOTAL_ Einträgen",
"infoEmpty": "Keine Daten vorhanden",
"infoFiltered": "(gefiltert von _MAX_ Einträgen)",
"infoPostFix": "",
"infoThousands": ".",
"lengthLabels": {
"-1": "Alle"
},
"lengthMenu": "_MENU_ Zeilen anzeigen",
"loadingRecords": "Wird geladen ..",
"orderClear": "Sortierung leeren",
"processing": "Bitte warten ..",
"search": "Suche:",
"searchBuilder": {
"add": "Bedingung hinzufügen",
"button": {
"_": "Such-Baukasten (%d)",
"0": "Such-Baukasten"
},
"clearAll": "Alle entfernen",
"condition": "Bedingung",
"conditions": {
"array": {
"contains": "enthält",
"empty": "ist leer",
"equals": "ist gleich",
"not": "ist ungleich",
"notEmpty": "ist nicht leer",
"without": "aber nicht"
},
"date": {
"after": "Nach",
"before": "Vor",
"between": "Zwischen",
"empty": "Leer",
"equals": "Gleich",
"not": "Nicht",
"notBetween": "Nicht zwischen",
"notEmpty": "Nicht leer"
},
"number": {
"between": "Zwischen",
"empty": "Leer",
"equals": "Entspricht",
"gt": "Größer als",
"gte": "Größer als oder gleich",
"lt": "Kleiner als",
"lte": "Kleiner als oder gleich",
"not": "Nicht",
"notBetween": "Nicht zwischen",
"notEmpty": "Nicht leer"
},
"string": {
"contains": "Beinhaltet",
"empty": "Leer",
"endsWith": "Endet mit",
"equals": "Entspricht",
"not": "Nicht",
"notContains": "enthält nicht",
"notEmpty": "Nicht leer",
"notEndsWith": "endet nicht mit",
"notStartsWith": "startet nicht mit",
"startsWith": "Startet mit"
}
},
"data": "Daten",
"deleteTitle": "Filterregel entfernen",
"leftTitle": "Äußere Kriterien",
"logicAnd": "Und",
"logicOr": "Oder",
"rightTitle": "Innere Kriterien",
"search": "Suche",
"title": {
"_": "Such-Baukasten (%d)",
"0": "Such-Baukasten"
},
"value": "Wert"
},
"searchPanes": {
"clearMessage": "Leeren",
"collapse": {
"_": "Suchmasken (%d)",
"0": "Suchmasken"
},
"collapseMessage": "Alle einklappen",
"count": "{total}",
"countFiltered": "{shown} ({total})",
"emptyMessage": "<em>Leer<\/em>",
"emptyPanes": "Keine Suchmasken",
"loadMessage": "Lade Suchmasken ..",
"showMessage": "zeige Alle",
"title": "Aktive Filter: %d"
},
"searchPlaceholder": "",
"select": {
"cells": {
"_": "%d Zellen ausgewählt",
"0": "",
"1": "1 Zelle ausgewählt"
},
"columns": {
"_": "%d Spalten ausgewählt",
"0": "",
"1": "1 Spalte ausgewählt"
},
"rows": {
"_": "%d Zeilen ausgewählt",
"0": "",
"1": "1 Zeile ausgewählt"
}
},
"stateRestore": {
"creationModal": {
"button": "Erstellen",
"columns": {
"search": "Spalten Suche",
"visible": "Spalten Sichtbarkeit"
},
"name": "Name:",
"order": "Sortieren",
"paging": "Seiten",
"scroller": "Scroll Position",
"search": "Suche",
"searchBuilder": "Such-Baukasten",
"select": "Auswahl",
"title": "Neue Ansicht erstellen",
"toggleLabel": "Inkludiert:"
},
"duplicateError": "Eine Ansicht mit diesem Namen existiert bereits.",
"emptyError": "Name darf nicht leer sein.",
"emptyStates": "Keine gespeicherten Ansichten",
"removeConfirm": "Sicher dass %s entfernt werden soll?",
"removeError": "Entfernen der Ansicht fehlgeschlagen.",
"removeJoiner": " und ",
"removeSubmit": "Entfernen",
"removeTitle": "Ansicht entfernen",
"renameButton": "Umbenennen",
"renameLabel": "Neuer Name für %s:",
"renameTitle": "Ansicht umbenennen"
},
"thousands": ".",
"zeroRecords": "Keine passenden Einträge gefunden"
}

View File

@ -0,0 +1,248 @@
{
"aria": {
"paginate": {
"first": "First",
"last": "Last",
"next": "Next",
"previous": "Previous"
}
},
"autoFill": {
"cancel": "Cancel",
"fill": "Fill all cells with <i>%d<\/i>",
"fillHorizontal": "Fill cells horizontally",
"fillVertical": "Fill cells vertically",
"info": ""
},
"buttons": {
"collection": "Collection <span class='ui-button-icon-primary ui-icon ui-icon-triangle-1-s'\/>",
"colvis": "Column Visibility",
"colvisRestore": "Restore visibility",
"copy": "Copy",
"copyKeys": "Press ctrl or u2318 + C to copy the table data to your system clipboard.<br><br>To cancel, click this message or press escape.",
"copySuccess": {
"_": "Copied %d rows to clipboard",
"1": "Copied 1 row to clipboard"
},
"copyTitle": "Copy to Clipboard",
"createState": "Create State",
"csv": "CSV",
"excel": "Excel",
"pageLength": {
"_": "Show %d rows",
"-1": "Show all rows"
},
"pdf": "PDF",
"print": "Print",
"removeAllStates": "Remove All States",
"removeState": "Remove",
"renameState": "Rename",
"savedStates": "Saved States",
"stateRestore": "State %d",
"updateState": "Update"
},
"datetime": {
"amPm": {
"0": "am",
"1": "pm"
},
"hours": "Hour",
"minutes": "Minute",
"months": {
"0": "January",
"1": "February",
"10": "November",
"11": "December",
"2": "March",
"3": "April",
"4": "May",
"5": "June",
"6": "July",
"7": "August",
"8": "September",
"9": "October"
},
"next": "Next",
"previous": "Previous",
"seconds": "Second",
"unknown": "-",
"weekdays": {
"0": "Sun",
"1": "Mon",
"2": "Tue",
"3": "Wed",
"4": "Thu",
"5": "Fri",
"6": "Sat"
}
},
"decimal": "",
"editor": {
"close": "Close",
"create": {
"button": "New",
"submit": "Create",
"title": "Create new entry"
},
"edit": {
"button": "Edit",
"submit": "Update",
"title": "Edit Entry"
},
"error": {
"system": "A system error has occurred (<a target=\"\\\" rel=\"nofollow\" href=\"\\\">More information<\/a>)."
},
"multi": {
"info": "The selected items contain different values for this input. To edit and set all items for this input to the same value, click or tap here, otherwise they will retain their individual values.",
"noMulti": "This input can be edited individually, but not part of a group. ",
"restore": "Undo Changes",
"title": "Multiple Values"
},
"remove": {
"button": "Delete",
"confirm": {
"_": "Are you sure you wish to delete %d rows?",
"1": "Are you sure you wish to delete 1 row?"
},
"submit": "Delete",
"title": "Delete"
}
},
"emptyTable": "No data available in table",
"info": "Showing _START_ to _END_ of _TOTAL_ entries",
"infoEmpty": "Showing 0 to 0 of 0 entries",
"infoFiltered": "(filtered from _MAX_ total entries)",
"infoPostFix": "",
"infoThousands": ",",
"lengthMenu": "Show _MENU_ entries",
"loadingRecords": "Loading...",
"processing": "Processing...",
"search": "Search:",
"searchBuilder": {
"add": "Add Condition",
"button": {
"_": "Search Builder (%d)",
"0": "Search Builder"
},
"clearAll": "Clear All",
"condition": "Condition",
"conditions": {
"array": {
"contains": "Contains",
"empty": "Empty",
"equals": "Equals",
"not": "Not",
"notEmpty": "Not Empty",
"without": "Without"
},
"date": {
"after": "After",
"before": "Before",
"between": "Between",
"empty": "Empty",
"equals": "Equals",
"not": "Not",
"notBetween": "Not Between",
"notEmpty": "Not Empty"
},
"number": {
"between": "Between",
"empty": "Empty",
"equals": "Equals",
"gt": "Greater Than",
"gte": "Greater Than Equal To",
"lt": "Less Than",
"lte": "Less Than Equal To",
"not": "Not",
"notBetween": "Not Between",
"notEmpty": "Not Empty"
},
"string": {
"contains": "Contains",
"empty": "Empty",
"endsWith": "Ends With",
"equals": "Equals",
"not": "Not",
"notContains": "Does Not Contain",
"notEmpty": "Not Empty",
"notEndsWith": "Does Not End With",
"notStartsWith": "Does Not Start With",
"startsWith": "Starts With"
}
},
"data": "Data",
"deleteTitle": "Delete filtering rule",
"leftTitle": "Outdent Criteria",
"logicAnd": "And",
"logicOr": "Or",
"rightTitle": "Indent Criteria",
"title": {
"_": "Search Builder (%d)",
"0": "Search Builder"
},
"value": "Value"
},
"searchPanes": {
"clearMessage": "Clear All",
"collapse": {
"_": "SearchPanes (%d)",
"0": "SearchPanes"
},
"collapseMessage": "Collapse All",
"count": "{total}",
"countFiltered": "{shown} ({total})",
"emptyPanes": "No SearchPanes",
"loadMessage": "Loading SearchPanes",
"showMessage": "Show All",
"title": "Filters Active - %d"
},
"searchPlaceholder": "",
"select": {
"cells": {
"_": "%d cells selected",
"0": "",
"1": "1 cell selected"
},
"columns": {
"_": "%d columns selected",
"0": "",
"1": "1 column selected"
},
"rows": {
"_": "%d rows selected",
"0": "",
"1": "1 row selected"
}
},
"stateRestore": {
"creationModal": {
"button": "Create",
"columns": {
"search": "Column Search",
"visible": "Column Visibility"
},
"name": "Name:",
"order": "Sorting",
"paging": "Paging",
"scroller": "Scroll Position",
"search": "Search",
"searchBuilder": "SearchBuilder",
"select": "Select",
"title": "Create New State",
"toggleLabel": "Includes:"
},
"duplicateError": "A state with this name already exists.",
"emptyError": "Name cannot be empty.",
"emptyStates": "No saved states",
"removeConfirm": "Are you sure you want to remove %s?",
"removeError": "Failed to remove state.",
"removeJoiner": " and ",
"removeSubmit": "Remove",
"removeTitle": "Remove State",
"renameButton": "Rename",
"renameLabel": "New Name for %s:",
"renameTitle": "Rename State"
},
"thousands": ",",
"zeroRecords": "No matching records found"
}

View File

@ -0,0 +1,313 @@
{
"aria": {
"orderable": "Activar para ordenar",
"orderableRemove": "Activar para quitar ordenación",
"orderableReverse": "Activar para ordenar de forma inversa",
"paginate": {
"first": "Primero",
"last": "Último",
"next": "Siguiente",
"previous": "Anterior"
}
},
"autoFill": {
"cancel": "Cancelar",
"fill": "Rellene todas las celdas con <i>%d<\/i>",
"fillHorizontal": "Rellenar celdas horizontalmente",
"fillVertical": "Rellenar celdas verticalmente",
"info": ""
},
"buttons": {
"collection": "Colección",
"colvis": "Visibilidad",
"colvisRestore": "Restaurar visibilidad",
"copy": "Copiar",
"copyKeys": "Presione ctrl o u2318 + C para copiar los datos de la tabla al portapapeles del sistema. <br \/> <br \/> Para cancelar, haga clic en este mensaje o presione escape.",
"copySuccess": {
"_": "Copiadas %ds filas al portapapeles",
"1": "Copiada 1 fila al portapapeles"
},
"copyTitle": "Copiar al portapapeles",
"createState": "Crear Estado",
"csv": "CSV",
"excel": "Excel",
"pageLength": {
"_": "Mostrar %d filas",
"-1": "Mostrar todas las filas",
"1": "Mostrar 1 fila"
},
"pdf": "PDF",
"print": "Imprimir",
"removeAllStates": "Remover Estados",
"removeState": "Remover",
"renameState": "Cambiar nombre",
"savedStates": "Estados Guardados",
"stateRestore": "Estado %d",
"updateState": "Actualizar"
},
"columnControl": {
"buttons": {
"searchClear": "Borrar búsqueda"
},
"colVis": "Visibilidad",
"colVisDropdown": "Desplegable visibilidad",
"dropdown": "Desplegable",
"list": {
"all": "Añadir",
"empty": "Vacío",
"none": "Ninguno",
"search": "Buscar.."
},
"orderAddAsc": "Añadir a ordenación ascendente",
"orderAddDesc": "Añadir a ordenación descencente",
"orderAsc": "Ordenar ascendentemente",
"orderClear": "Borrar ordenación",
"orderDesc": "Ordenar descendentemente",
"orderRemove": "Borrar de ordenación",
"reorder": "Reordenar",
"reorderLeft": "Mover a la izquierda",
"reorderRight": "Mover a la derecha",
"search": {
"datetime": {
"empty": "Vacío",
"equal": "Igual a",
"greater": "Mayor que",
"less": "Menor que",
"notEmpty": "No vacío",
"notEqual": "Diferente de"
},
"number": {
"empty": "Vacío",
"equal": "Igual a",
"greater": "Mayor que",
"greaterOrEqual": "Mayor o igual a",
"less": "Menor que",
"lessOrEqual": "Menor o igual a",
"notEmpty": "No vacío",
"notEqual": "Diferente de"
},
"text": {
"contains": "Contiene",
"empty": "Vacío",
"ends": "Finaliza con",
"equal": "Igual a",
"notContains": "no contiene",
"notEmpty": "No vacío",
"notEqual": "Diferente de",
"starts": "Empieza con"
}
},
"searchClear": "Borrar búsqueda",
"searchDropdown": "Buscar"
},
"datetime": {
"amPm": {
"0": "AM",
"1": "PM"
},
"hours": "Horas",
"minutes": "Minutos",
"months": {
"0": "Enero",
"1": "Febrero",
"10": "Noviembre",
"11": "Diciembre",
"2": "Marzo",
"3": "Abril",
"4": "Mayo",
"5": "Junio",
"6": "Julio",
"7": "Agosto",
"8": "Septiembre",
"9": "Octubre"
},
"next": "Próximo",
"previous": "Anterior",
"seconds": "Segundos",
"unknown": "-",
"weekdays": {
"0": "Dom",
"1": "Lun",
"2": "Mar",
"3": "Mié",
"4": "Jue",
"5": "Vie",
"6": "Sáb"
}
},
"decimal": "",
"editor": {
"close": "Cerrar",
"create": {
"button": "Nuevo",
"submit": "Crear",
"title": "Crear Nuevo Registro"
},
"edit": {
"button": "Editar",
"submit": "Actualizar",
"title": "Editar Registro"
},
"error": {
"system": "Ha ocurrido un error en el sistema (<a target=\"\\\" rel=\"\\ nofollow\" href=\"\\\">Más información&lt;\\\/a&gt;).<\/a>"
},
"multi": {
"info": "Los elementos seleccionados contienen diferentes valores para este registro. Para editar y establecer todos los elementos de este registro con el mismo valor, haga clic o pulse aquí, de lo contrario conservarán sus valores individuales.",
"noMulti": "Este registro puede ser editado individualmente, pero no como parte de un grupo.",
"restore": "Deshacer Cambios",
"title": "Múltiples Valores"
},
"remove": {
"button": "Eliminar",
"confirm": {
"_": "¿Está seguro de que desea eliminar %d filas?",
"1": "¿Está seguro de que desea eliminar 1 fila?"
},
"submit": "Eliminar",
"title": "Eliminar Registro"
}
},
"emptyTable": "Ningún dato disponible en esta tabla",
"info": "Mostrando _START_ a _END_ de _TOTAL_ registros",
"infoEmpty": "Mostrando registros del 0 al 0 de un total de 0 registros",
"infoFiltered": "(filtrado de un total de _MAX_ registros)",
"infoPostFix": "",
"infoThousands": ".",
"lengthLabels": {
"-1": "Todas"
},
"lengthMenu": "Mostrar _MENU_ registros",
"loadingRecords": "Cargando...",
"orderClear": "Limpiar ordenación de toda la tabla",
"processing": "Procesando...",
"search": "Buscar:",
"searchBuilder": {
"add": "Añadir condición",
"button": {
"_": "Constructor de búsqueda (%d)",
"0": "Constructor de búsqueda"
},
"clearAll": "Borrar todo",
"condition": "Condición",
"conditions": {
"array": {
"contains": "Contiene",
"empty": "Vacío",
"equals": "Igual",
"not": "Diferente de",
"notEmpty": "No Vacío",
"without": "Sin"
},
"date": {
"after": "Después",
"before": "Antes",
"between": "Entre",
"empty": "Vacío",
"equals": "Igual a",
"not": "Diferente de",
"notBetween": "No entre",
"notEmpty": "No Vacío"
},
"number": {
"between": "Entre",
"empty": "Vacío",
"equals": "Igual a",
"gt": "Mayor a",
"gte": "Mayor o igual a",
"lt": "Menor que",
"lte": "Menor o igual que",
"not": "Diferente de",
"notBetween": "No entre",
"notEmpty": "No vacío"
},
"string": {
"contains": "Contiene",
"empty": "Vacío",
"endsWith": "Termina en",
"equals": "Igual a",
"not": "Diferente de",
"notContains": "No Contiene",
"notEmpty": "No Vacío",
"notEndsWith": "No termina con",
"notStartsWith": "No empieza con",
"startsWith": "Empieza con"
}
},
"data": "Data",
"deleteTitle": "Eliminar regla de filtrado",
"leftTitle": "Criterios anulados",
"logicAnd": "Y",
"logicOr": "O",
"rightTitle": "Criterios de sangría",
"search": "Buscar",
"title": {
"_": "Constructor de búsqueda (%d)",
"0": "Constructor de búsqueda"
},
"value": "Valor"
},
"searchPanes": {
"clearMessage": "Borrar todo",
"collapse": {
"_": "Paneles de búsqueda (%d)",
"0": "Paneles de búsqueda"
},
"collapseMessage": "Colapsar Todo",
"count": "{total}",
"countFiltered": "{shown} ({total})",
"emptyMessage": "vacío",
"emptyPanes": "Sin paneles de búsqueda",
"loadMessage": "Cargando paneles de búsqueda",
"showMessage": "Mostrar Todo",
"title": "Filtros Activos - %d"
},
"searchPlaceholder": "",
"select": {
"cells": {
"_": "%d celdas seleccionadas",
"0": "",
"1": "1 celda seleccionada"
},
"columns": {
"_": "%d columnas seleccionadas",
"0": "",
"1": "1 columna seleccionada"
},
"rows": {
"_": "%d filas seleccionadas",
"0": "",
"1": "1 fila seleccionada"
}
},
"stateRestore": {
"creationModal": {
"button": "Crear",
"columns": {
"search": "Búsqueda de Columna",
"visible": "Visibilidad de Columna"
},
"name": "Nombre:",
"order": "Clasificación",
"paging": "Paginación",
"scroller": "Posición de desplazamiento",
"search": "Búsqueda",
"searchBuilder": "Búsqueda avanzada",
"select": "Seleccionar",
"title": "Crear Nuevo Estado",
"toggleLabel": "Incluir:"
},
"duplicateError": "Ya existe un Estado con este nombre.",
"emptyError": "El nombre no puede estar vacío.",
"emptyStates": "No hay Estados guardados",
"removeConfirm": "¿Seguro que quiere eliminar %s?",
"removeError": "Error al eliminar el Estado",
"removeJoiner": "y",
"removeSubmit": "Eliminar",
"removeTitle": "Remover Estado",
"renameButton": "Cambiar Nombre",
"renameLabel": "Nuevo nombre para %s:",
"renameTitle": "Cambiar Nombre Estado"
},
"thousands": ".",
"zeroRecords": "No se encontraron resultados"
}

View File

@ -0,0 +1,313 @@
{
"aria": {
"orderable": "Activer pour trier",
"orderableRemove": "Activer pour supprimer le tri",
"orderableReverse": "Activer pour inverser le tri",
"paginate": {
"first": "Première",
"last": "Dernière",
"next": "Suivante",
"previous": "Précédente"
}
},
"autoFill": {
"cancel": "Annuler",
"fill": "Remplir toutes les cellules avec <i>%d<\/i>",
"fillHorizontal": "Remplir les cellules horizontalement",
"fillVertical": "Remplir les cellules verticalement",
"info": ""
},
"buttons": {
"collection": "Collection",
"colvis": "Visibilité colonnes",
"colvisRestore": "Rétablir visibilité",
"copy": "Copier",
"copyKeys": "Appuyez sur ctrl ou u2318 + C pour copier les données du tableau dans votre presse-papier.",
"copySuccess": {
"_": "%d lignes copiées dans le presse-papier",
"1": "1 ligne copiée dans le presse-papier"
},
"copyTitle": "Copier dans le presse-papier",
"createState": "Créer un état",
"csv": "CSV",
"excel": "Excel",
"pageLength": {
"_": "Afficher %d lignes",
"-1": "Afficher toutes les lignes",
"1": "Afficher 1 ligne"
},
"pdf": "PDF",
"print": "Imprimer",
"removeAllStates": "Supprimer tous les états",
"removeState": "Supprimer",
"renameState": "Renommer",
"savedStates": "États sauvegardés",
"stateRestore": "État %d",
"updateState": "Mettre à jour"
},
"columnControl": {
"buttons": {
"searchClear": "Effacer la recherche"
},
"colVis": "Visibilité colonnes",
"colVisDropdown": "Visibilité colonnes",
"dropdown": "Plus...",
"list": {
"all": "Tout sélectionner",
"empty": "Vide",
"none": "Désélectionner",
"search": "Rechercher..."
},
"orderAddAsc": "Ajouter tri croissant",
"orderAddDesc": "Ajouter tri décroissant",
"orderAsc": "Tri croissant",
"orderClear": "Effacer le tri",
"orderDesc": "Tri décroissant",
"orderRemove": "Supprimer du tri",
"reorder": "Réorganiser les colonnes",
"reorderLeft": "Déplacer la colonne vers la gauche",
"reorderRight": "Déplacer la colonne vers la droite",
"search": {
"datetime": {
"empty": "Vide",
"equal": "Égal à",
"greater": "Après le",
"less": "Avant le",
"notEmpty": "Non vide",
"notEqual": "Différent de"
},
"number": {
"empty": "Vide",
"equal": "Égal à",
"greater": "Supérieur à",
"greaterOrEqual": "Supérieur ou égal à",
"less": "Inférieur à",
"lessOrEqual": "Inférieur ou égal à",
"notEmpty": "Non vide",
"notEqual": "Différent de"
},
"text": {
"contains": "Contient",
"empty": "Vide",
"ends": "Se termine par",
"equal": "Égal à",
"notContains": "Ne contient pas",
"notEmpty": "Non vide",
"notEqual": "Différent de",
"starts": "Commence par"
}
},
"searchClear": "Effacer la recherche",
"searchDropdown": "Rechercher"
},
"datetime": {
"amPm": {
"0": "am",
"1": "pm"
},
"hours": "Heures",
"minutes": "Minutes",
"months": {
"0": "Janvier",
"1": "Février",
"10": "Novembre",
"11": "Décembre",
"2": "Mars",
"3": "Avril",
"4": "Mai",
"5": "Juin",
"6": "Juillet",
"7": "Août",
"8": "Septembre",
"9": "Octobre"
},
"next": "Suivant",
"previous": "Précédent",
"seconds": "Secondes",
"unknown": "-",
"weekdays": {
"0": "Dim",
"1": "Lun",
"2": "Mar",
"3": "Mer",
"4": "Jeu",
"5": "Ven",
"6": "Sam"
}
},
"decimal": "",
"editor": {
"close": "Fermer",
"create": {
"button": "Nouveau",
"submit": "Créer",
"title": "Créer une nouvelle entrée"
},
"edit": {
"button": "Editer",
"submit": "Mettre à jour",
"title": "Editer Entrée"
},
"error": {
"system": "Une erreur système s'est produite (<a target=\"\\\" rel=\"nofollow\" href=\"\\\">Plus d'information<\/a>)."
},
"multi": {
"info": "Les éléments sélectionnés contiennent différentes valeurs pour cette entrée. Pour modifier et définir tous les éléments de cette entrée à la même valeur, cliquez ou tapez ici, sinon ils conserveront leurs valeurs individuelles.",
"noMulti": "Ce champ peut être modifié individuellement, mais ne fait pas partie d'un groupe. ",
"restore": "Annuler les modifications",
"title": "Valeurs multiples"
},
"remove": {
"button": "Supprimer",
"confirm": {
"_": "Êtes-vous sûr de vouloir supprimer %d lignes ?",
"1": "Êtes-vous sûr de vouloir supprimer 1 ligne ?"
},
"submit": "Supprimer",
"title": "Supprimer"
}
},
"emptyTable": "Aucune donnée disponible dans le tableau",
"info": "Affichage de _START_ à _END_ sur _TOTAL_ entrées",
"infoEmpty": "Affichage de 0 à 0 sur 0 entrées",
"infoFiltered": "(filtrées depuis un total de _MAX_ entrées)",
"infoPostFix": "",
"infoThousands": " ",
"lengthLabels": {
"-1": "Tout"
},
"lengthMenu": "Afficher _MENU_ entrées",
"loadingRecords": "Chargement...",
"orderClear": "Effacer le tri",
"processing": "Traitement...",
"search": "Rechercher :",
"searchBuilder": {
"add": "Ajouter une condition",
"button": {
"_": "Recherche avancée (%d)",
"0": "Recherche avancée"
},
"clearAll": "Effacer tout",
"condition": "Condition",
"conditions": {
"array": {
"contains": "Contient",
"empty": "Vide",
"equals": "Égal à",
"not": "Différent de",
"notEmpty": "Non vide",
"without": "Sans"
},
"date": {
"after": "Après le",
"before": "Avant le",
"between": "Entre",
"empty": "Vide",
"equals": "Égal à",
"not": "Différent de",
"notBetween": "Pas entre",
"notEmpty": "Non vide"
},
"number": {
"between": "Entre",
"empty": "Vide",
"equals": "Égal à",
"gt": "Supérieur à",
"gte": "Supérieur ou égal à",
"lt": "Inférieur à",
"lte": "Inférieur ou égal à",
"not": "Différent de",
"notBetween": "Pas entre",
"notEmpty": "Non vide"
},
"string": {
"contains": "Contient",
"empty": "Vide",
"endsWith": "Se termine par",
"equals": "Égal à",
"not": "Différent de",
"notContains": "Ne contient pas",
"notEmpty": "Non vide",
"notEndsWith": "Ne termine pas par",
"notStartsWith": "Ne commence pas par",
"startsWith": "Commence par"
}
},
"data": "Donnée",
"deleteTitle": "Supprimer la règle de filtrage",
"leftTitle": "Désindenter le critère",
"logicAnd": "Et",
"logicOr": "Ou",
"rightTitle": "Indenter le critère",
"search": "Rechercher",
"title": {
"_": "Recherche avancée (%d)",
"0": "Recherche avancée"
},
"value": "Valeur"
},
"searchPanes": {
"clearMessage": "Effacer tout",
"collapse": {
"_": "Volet de recherche (%d)",
"0": "Volet de recherche"
},
"collapseMessage": "Réduire tout",
"count": "{total}",
"countFiltered": "{shown} ({total})",
"emptyMessage": "<em>vide<\/em>",
"emptyPanes": "Pas de volet de recherche",
"loadMessage": "Chargement du volet de recherche...",
"showMessage": "Montrer tout",
"title": "Filtres actifs - %d"
},
"searchPlaceholder": "",
"select": {
"cells": {
"_": "%d cellules sélectionnées",
"0": "",
"1": "1 cellule sélectionnée"
},
"columns": {
"_": "%d colonnes sélectionnées",
"0": "",
"1": "1 colonne sélectionnée"
},
"rows": {
"_": "%d lignes sélectionnées",
"0": "",
"1": "1 ligne sélectionnée"
}
},
"stateRestore": {
"creationModal": {
"button": "Créer",
"columns": {
"search": "Recherche par colonne",
"visible": "Visibilité des colonnes"
},
"name": "Nom :",
"order": "Tri",
"paging": "Pagination",
"scroller": "Position du défilement",
"search": "Recherche",
"searchBuilder": "Recherche avancée",
"select": "Sélection",
"title": "Créer un nouvel état",
"toggleLabel": "Inclus :"
},
"duplicateError": "Il existe déjà un état avec ce nom.",
"emptyError": "Le nom ne peut pas être vide.",
"emptyStates": "Aucun état sauvegardé",
"removeConfirm": "Voulez vous vraiment supprimer %s ?",
"removeError": "Échec de la suppression de l'état.",
"removeJoiner": "et",
"removeSubmit": "Supprimer",
"removeTitle": "Supprimer l'état",
"renameButton": "Renommer",
"renameLabel": "Nouveau nom pour %s :",
"renameTitle": "Renommer l'état"
},
"thousands": " ",
"zeroRecords": "Aucune entrée correspondante trouvée"
}

View File

@ -0,0 +1,248 @@
{
"aria": {
"paginate": {
"first": "Primeiro",
"last": "Último",
"next": "Próximo",
"previous": "Anterior"
}
},
"autoFill": {
"cancel": "Cancelar",
"fill": "Preencher todas as células com",
"fillHorizontal": "Preencher células horizontalmente",
"fillVertical": "Preencher células verticalmente",
"info": ""
},
"buttons": {
"collection": "Coleção <span class=\"ui-button-icon-primary ui-icon ui-icon-triangle-1-s\"><\/span>",
"colvis": "Visibilidade da Coluna",
"colvisRestore": "Restaurar Visibilidade",
"copy": "Copiar",
"copyKeys": "Pressione ctrl ou u2318 + C para copiar os dados da tabela para a área de transferência do sistema. Para cancelar, clique nesta mensagem ou pressione Esc..",
"copySuccess": {
"_": "%d linhas copiadas com sucesso",
"1": "Uma linha copiada com sucesso"
},
"copyTitle": "Copiar para a Área de Transferência",
"createState": "Criar estado",
"csv": "CSV",
"excel": "Excel",
"pageLength": {
"_": "Mostrar %d registros",
"-1": "Mostrar todos os registros"
},
"pdf": "PDF",
"print": "Imprimir",
"removeAllStates": "Remover todos os estados",
"removeState": "Remover",
"renameState": "Renomear",
"savedStates": "Estados salvos",
"stateRestore": "Estado %d",
"updateState": "Atualizar"
},
"datetime": {
"amPm": {
"0": "am",
"1": "pm"
},
"hours": "Hora",
"minutes": "Minuto",
"months": {
"0": "Janeiro",
"1": "Fevereiro",
"10": "Novembro",
"11": "Dezembro",
"2": "Março",
"3": "Abril",
"4": "Maio",
"5": "Junho",
"6": "Julho",
"7": "Agosto",
"8": "Setembro",
"9": "Outubro"
},
"next": "Próximo",
"previous": "Anterior",
"seconds": "Segundo",
"unknown": "-",
"weekdays": {
"0": "Dom",
"1": "Seg",
"2": "Ter",
"3": "Qua",
"4": "Qui",
"5": "Sex",
"6": "Sáb"
}
},
"decimal": "",
"editor": {
"close": "Fechar",
"create": {
"button": "Novo",
"submit": "Criar",
"title": "Criar novo registro"
},
"edit": {
"button": "Editar",
"submit": "Atualizar",
"title": "Editar registro"
},
"error": {
"system": "Ocorreu um erro no sistema (<a target=\"\\\" rel=\"nofollow\" href=\"\\\">Mais informações<\/a>)."
},
"multi": {
"info": "Os itens selecionados contêm valores diferentes para esta entrada. Para editar e definir todos os itens para esta entrada com o mesmo valor, clique ou toque aqui, caso contrário, eles manterão seus valores individuais.",
"noMulti": "Essa entrada pode ser editada individualmente, mas não como parte do grupo",
"restore": "Desfazer alterações",
"title": "Multiplos valores"
},
"remove": {
"button": "Remover",
"confirm": {
"_": "Tem certeza que quer deletar %d linhas?",
"1": "Tem certeza que quer deletar 1 linha?"
},
"submit": "Remover",
"title": "Remover registro"
}
},
"emptyTable": "Nenhum registro encontrado",
"info": "Mostrando de _START_ até _END_ de _TOTAL_ registros",
"infoEmpty": "Mostrando 0 até 0 de 0 registro(s)",
"infoFiltered": "(Filtrados de _MAX_ registros)",
"infoPostFix": "",
"infoThousands": ".",
"lengthMenu": "Exibir _MENU_ resultados por página",
"loadingRecords": "Carregando...",
"processing": "Carregando...",
"search": "Pesquisar",
"searchBuilder": {
"add": "Adicionar Condição",
"button": {
"_": "Construtor de Pesquisa (%d)",
"0": "Construtor de Pesquisa"
},
"clearAll": "Limpar Tudo",
"condition": "Condição",
"conditions": {
"array": {
"contains": "Contém",
"empty": "Vazio",
"equals": "Igual à",
"not": "Não",
"notEmpty": "Não vazio",
"without": "Não possui"
},
"date": {
"after": "Depois",
"before": "Antes",
"between": "Entre",
"empty": "Vazio",
"equals": "Igual",
"not": "Não",
"notBetween": "Não Entre",
"notEmpty": "Não Vazio"
},
"number": {
"between": "Entre",
"empty": "Vazio",
"equals": "Igual",
"gt": "Maior Que",
"gte": "Maior ou Igual a",
"lt": "Menor Que",
"lte": "Menor ou Igual a",
"not": "Não",
"notBetween": "Não Entre",
"notEmpty": "Não Vazio"
},
"string": {
"contains": "Contém",
"empty": "Vazio",
"endsWith": "Termina Com",
"equals": "Igual",
"not": "Não",
"notContains": "Não contém",
"notEmpty": "Não Vazio",
"notEndsWith": "Não termina com",
"notStartsWith": "Não começa com",
"startsWith": "Começa Com"
}
},
"data": "Data",
"deleteTitle": "Excluir regra de filtragem",
"leftTitle": "Critérios Externos",
"logicAnd": "E",
"logicOr": "Ou",
"rightTitle": "Critérios Internos",
"title": {
"_": "Construtor de Pesquisa (%d)",
"0": "Construtor de Pesquisa"
},
"value": "Valor"
},
"searchPanes": {
"clearMessage": "Limpar Tudo",
"collapse": {
"_": "Painéis de Pesquisa (%d)",
"0": "Painéis de Pesquisa"
},
"collapseMessage": "Fechar todos",
"count": "{total}",
"countFiltered": "{shown} ({total})",
"emptyPanes": "Nenhum Painel de Pesquisa",
"loadMessage": "Carregando Painéis de Pesquisa...",
"showMessage": "Mostrar todos",
"title": "Filtros Ativos"
},
"searchPlaceholder": "",
"select": {
"cells": {
"_": "%d células selecionadas",
"0": "",
"1": "1 célula selecionada"
},
"columns": {
"_": "%d colunas selecionadas",
"0": "",
"1": "1 coluna selecionada"
},
"rows": {
"_": "Selecionado %d linhas",
"0": "",
"1": "Selecionado 1 linha"
}
},
"stateRestore": {
"creationModal": {
"button": "Criar",
"columns": {
"search": "Busca de colunas",
"visible": "Visibilidade da coluna"
},
"name": "Nome:",
"order": "Ordernar",
"paging": "Paginação",
"scroller": "Posição da barra de rolagem",
"search": "Busca",
"searchBuilder": "Mecanismo de busca",
"select": "Selecionar",
"title": "Criar novo estado",
"toggleLabel": "Inclui:"
},
"duplicateError": "Já existe um estado com esse nome!",
"emptyError": "Não pode ser vazio!",
"emptyStates": "Nenhum estado salvo",
"removeConfirm": "Confirma remover %s?",
"removeError": "Falha ao remover estado!",
"removeJoiner": "e",
"removeSubmit": "Remover",
"removeTitle": "Remover estado",
"renameButton": "Renomear",
"renameLabel": "Novo nome para %s:",
"renameTitle": "Renomear estado"
},
"thousands": ".",
"zeroRecords": "Nenhum registro encontrado"
}

View File

@ -0,0 +1,313 @@
{
"aria": {
"orderable": "Ativar para ordenar",
"orderableRemove": "Ativar para remover ordenação",
"orderableReverse": "Ativar para inverter ordenação",
"paginate": {
"first": "Primeiro",
"last": "Último",
"next": "Seguinte",
"previous": "Anterior"
}
},
"autoFill": {
"cancel": "Cancelar",
"fill": "Preencher",
"fillHorizontal": "Preencher células na horizontal",
"fillVertical": "Preencher células na vertical",
"info": ""
},
"buttons": {
"collection": "Coleção",
"colvis": "Visibilidade de colunas",
"colvisRestore": "Restaurar visibilidade",
"copy": "Copiar",
"copyKeys": "Pressionar CTRL ou u2318 + C para copiar a informação para a área de transferência.<br \/><br \/>Para cancelar, clique nesta mensagem ou pressione ESC.",
"copySuccess": {
"_": "%ds linhas copiadas para a área de transferência",
"1": "Uma linha copiada para a área de transferência"
},
"copyTitle": "Copiar para a área de transferência",
"createState": "Criar Estado",
"csv": "CSV",
"excel": "Excel",
"pageLength": {
"_": "Mostrar %d linhas",
"-1": "Mostrar todas as linhas",
"1": "Mostrar 1 linha"
},
"pdf": "PDF",
"print": "Imprimir",
"removeAllStates": "Remover Todos os Estados",
"removeState": "Remover",
"renameState": "Renomear",
"savedStates": "Estados Gravados",
"stateRestore": "Estado %d",
"updateState": "Atualizar"
},
"columnControl": {
"buttons": {
"searchClear": "Limpar pesquisa"
},
"colVis": "Visibilidade da coluna",
"colVisDropdown": "Visibilidade da coluna",
"dropdown": "Mostrar mais...",
"list": {
"all": "Todos",
"empty": "Vazio",
"none": "Nenhum",
"search": "Pesquisar..."
},
"orderAddAsc": "Adicionar à ordem crescente",
"orderAddDesc": "Adicionar à ordem decrescente",
"orderAsc": "Ordem crescente",
"orderClear": "Remover ordenação",
"orderDesc": "Ordem decrescente",
"orderRemove": "Remover ordenação",
"reorder": "Reordenar",
"reorderLeft": "Mover para a esquerda",
"reorderRight": "Mover para a direita",
"search": {
"datetime": {
"empty": "Vazio",
"equal": "Igual a",
"greater": "Posterior a",
"less": "Anterior a",
"notEmpty": "Não está vazio",
"notEqual": "Diferente de"
},
"number": {
"empty": "Vazio",
"equal": "Igual a",
"greater": "Maior que",
"greaterOrEqual": "Maior ou igual a",
"less": "Menor que",
"lessOrEqual": "Menor ou igual a",
"notEmpty": "Não está vazio",
"notEqual": "Diferente de"
},
"text": {
"contains": "Contém",
"empty": "Vazio",
"ends": "Termina em",
"equal": "Igual a",
"notContains": "Não contém",
"notEmpty": "Não está vazio",
"notEqual": "Diferente de",
"starts": "Começa por"
}
},
"searchClear": "Limpar pesquisa",
"searchDropdown": "Pesquisar"
},
"datetime": {
"amPm": {
"0": "am",
"1": "pm"
},
"hours": "Horas",
"minutes": "Minutos",
"months": {
"0": "Janeiro",
"1": "Fevereiro",
"10": "Novembro",
"11": "Dezembro",
"2": "Março",
"3": "Abril",
"4": "Maio",
"5": "Junho",
"6": "Julho",
"7": "Agosto",
"8": "Setembro",
"9": "Outubro"
},
"next": "Próximo",
"previous": "Anterior",
"seconds": "Segundos",
"unknown": "-",
"weekdays": {
"0": "Dom",
"1": "Seg",
"2": "Ter",
"3": "Qua",
"4": "Qui",
"5": "Sex",
"6": "Sáb"
}
},
"decimal": "",
"editor": {
"close": "Fechar",
"create": {
"button": "Novo",
"submit": "Criar",
"title": "Criar novo registo"
},
"edit": {
"button": "Editar",
"submit": "Atualizar",
"title": "Editar registo"
},
"error": {
"system": "Ocorreu um erro no sistema"
},
"multi": {
"info": "Os itens selecionados contêm valores diferentes para esta entrada. Para editar e definir todos os itens nesta entrada com o mesmo valor, clique ou toque aqui, caso contrário eles manterão os seus valores individuais.",
"noMulti": "Este campo pode ser editado individualmente mas não pode ser editado em grupo",
"restore": "Desfazer alterações",
"title": "Múltiplos valores"
},
"remove": {
"button": "Remover",
"confirm": {
"_": "Tem a certeza que pretende eliminar %d entradas?",
"1": "Tem a certeza que pretende eliminar esta entrada?"
},
"submit": "Remover",
"title": "Remover"
}
},
"emptyTable": "Não foi encontrado nenhum registo",
"info": "Mostrando os registos _START_ a _END_ num total de _TOTAL_",
"infoEmpty": "Mostrando 0 registos num total de 0",
"infoFiltered": "(filtrado num total de _MAX_ registos)",
"infoPostFix": "",
"infoThousands": ".",
"lengthLabels": {
"-1": "Todas"
},
"lengthMenu": "Mostrar _MENU_ registos",
"loadingRecords": "A carregar...",
"orderClear": "Remover ordenação",
"processing": "A processar...",
"search": "Procurar:",
"searchBuilder": {
"add": "Adicionar condição",
"button": {
"_": "Construtor de pesquisa (%d)",
"0": "Construtor de pesquisa"
},
"clearAll": "Limpar tudo",
"condition": "Condição",
"conditions": {
"array": {
"contains": "Contém",
"empty": "Vazio",
"equals": "Igual",
"not": "Diferente",
"notEmpty": "Não está vazio",
"without": "Sem"
},
"date": {
"after": "Depois",
"before": "Antes",
"between": "Entre",
"empty": "Vazio",
"equals": "Igual",
"not": "Diferente",
"notBetween": "Não está entre",
"notEmpty": "Não está vazio"
},
"number": {
"between": "Entre",
"empty": "Vazio",
"equals": "Igual",
"gt": "Maior que",
"gte": "Maior ou igual a",
"lt": "Menor que",
"lte": "Menor ou igual a",
"not": "Diferente",
"notBetween": "Não está entre",
"notEmpty": "Não está vazio"
},
"string": {
"contains": "Contém",
"empty": "Vazio",
"endsWith": "Termina em",
"equals": "Igual",
"not": "Diferente",
"notContains": "Não contém",
"notEmpty": "Não está vazio",
"notEndsWith": "Não termina com",
"notStartsWith": "Não começa com",
"startsWith": "Começa em"
}
},
"data": "Dados",
"deleteTitle": "Excluir condição de filtragem",
"leftTitle": "Excluir critério",
"logicAnd": "E",
"logicOr": "Ou",
"rightTitle": "Incluir critério",
"search": "Pesquisar",
"title": {
"_": "Construtor de pesquisa (%d)",
"0": "Construtor de pesquisa"
},
"value": "Valor"
},
"searchPanes": {
"clearMessage": "Limpar tudo",
"collapse": {
"_": "Painéis de pesquisa (%d)",
"0": "Painéis de pesquisa"
},
"collapseMessage": "Ocultar Todos",
"count": "{total}",
"countFiltered": "{shown} ({total})",
"emptyMessage": "<em>Vazio<\/em>",
"emptyPanes": "Sem painéis de pesquisa",
"loadMessage": "A carregar painéis de pesquisa",
"showMessage": "Mostrar todos",
"title": "Filtros ativos"
},
"searchPlaceholder": "",
"select": {
"cells": {
"_": "%d células selecionadas",
"0": "",
"1": "1 célula selecionada"
},
"columns": {
"_": "%d colunas selecionadas",
"0": "",
"1": "1 coluna selecionada"
},
"rows": {
"_": "%d linhas selecionadas",
"0": "",
"1": "%d linha selecionada"
}
},
"stateRestore": {
"creationModal": {
"button": "Criar",
"columns": {
"search": "Pesquisa por Colunas",
"visible": "Visibilidade das Colunas"
},
"name": "Nome:",
"order": "Ordenar",
"paging": "Paginação",
"scroller": "Posição da barra de Scroll",
"search": "Pesquisa",
"searchBuilder": "Pesquisa Avançada",
"select": "Selecionar",
"title": "Criar Novo Estado",
"toggleLabel": "Incluir:"
},
"duplicateError": "Já existe um estado com o mesmo nome",
"emptyError": "Nome não pode ser vazio",
"emptyStates": "Não existem estados gravados",
"removeConfirm": "Deseja mesmo remover o estado %s?",
"removeError": "Erro ao remover o estado.",
"removeJoiner": " e ",
"removeSubmit": "Apagar",
"removeTitle": "Apagar Estado",
"renameButton": "Renomear",
"renameLabel": "Novo nome para %s:",
"renameTitle": "Renomear Estado"
},
"thousands": ".",
"zeroRecords": "Não foram encontrados resultados"
}

View File

@ -1,4 +1,5 @@
<html th:lang="${#locale.language}" th:with="isAuth=${#authorization.expression('isAuthenticated()')}"
<html th:lang="${#locale.country != '' ? #locale.language + '-' + #locale.country : #locale.language}"
th:with="isAuth=${#authorization.expression('isAuthenticated()')}"
th:attrappend="data-layout=${isAuth} ? 'semibox' : 'horizontal'" data-sidebar-visibility="show" data-topbar="light"
data-sidebar="light" data-sidebar-size="lg" data-sidebar-image="none" data-preloader="disable"
xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/extras/spring-security" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">

View File

@ -10,6 +10,11 @@
<!-- CSRF obligatorio -->
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" />
<div th:if="${param.error}" class="alert alert-danger"
th:text="#{login.error}">
Credenciales inválidas
</div>
<div class="mb-3">
<label for="username" class="form-label" th:text="#{login.email}">Correo electrónico</label>
<input type="email" class="form-control" id="username" th:placeholder="#{login.email-placeholder}"
@ -33,8 +38,7 @@
<div class="form-check">
<input class="form-check-input" type="checkbox" value="" id="remember-me" name="remember-me">
<label class="form-check-label" for="remember-me"
th:text="#{login.rememberMe}">Recuerdame</label>
<label class="form-check-label" for="remember-me" th:text="#{login.rememberMe}">Recuerdame</label>
</div>
<div class="mt-4">

View File

@ -40,7 +40,7 @@
</a>
</li>
<li class="nav-item">
<a class="nav-link menu-link" href="/">
<a class="nav-link menu-link" href="/users">
<i class="ri-user-line"></i> <span th:text="#{app.sidebar.usuarios}">Usuarios</span>
</a>
</li>

View File

@ -46,7 +46,7 @@
<div class="dropdown-menu dropdown-menu-end">
<!-- item-->
<a href="javascript:void(0);" class="dropdown-item notify-item language" data-lang="es"
<a href="javascript:void(0);" class="dropdown-item notify-item language" data-lang="es-ES"
title="Spanish">
<img src="/assets/images/flags/spain.svg" alt="user-image" class="me-2 rounded"
height="18">
@ -54,7 +54,7 @@
</a>
<!-- item-->
<a href="javascript:void(0);" class="dropdown-item notify-item language py-2" data-lang="en"
<a href="javascript:void(0);" class="dropdown-item notify-item language py-2" data-lang="en-GB"
title="English">
<img src="/assets/images/flags/gb.svg" alt="user-image" class="me-2 rounded"
height="18">

View File

@ -0,0 +1,59 @@
<!doctype html>
<html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{imprimelibros/layout}">
<head>
<th:block layout:fragment="pagetitle" />
<th:block th:replace="~{imprimelibros/partials/head-css :: head-css}" />
<th:block layout:fragment="pagecss">
<link th:href="@{/assets/css/presupuestador.css}" rel="stylesheet"
th:unless="${#authorization.expression('isAuthenticated()')}" />
<link th:href="@{/assets/libs/datatables/dataTables.bootstrap5.min.css}" rel="stylesheet" />
</th:block>
</head>
<body>
<div th:replace="~{imprimelibros/partials/topbar :: topbar}" />
<div th:replace="~{imprimelibros/partials/sidebar :: sidebar}" />
<th:block layout:fragment="content">
<div th:if="${#authorization.expression('isAuthenticated()')}">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="/"><i class="ri-home-5-fill"></i></a></li>
<li class="breadcrumb-item active" aria-current="page" th:text="#{usuarios.titulo}">Usuarios</li>
</ol>
</nav>
<div class="container-fluid">
<table id="users-datatable" class="table table-striped table-nowrap responsive w-100">
<thead>
<tr>
<th scope="col" th:text="#{usuarios.tabla.nombre}">Nombre</th>
<th scope="col" th:text="#{usuarios.tabla.email}">Correo electrónico</th>
<th scope="col" th:text="#{usuarios.tabla.rol}">Rol</th>
<th scope="col" th:text="#{usuarios.tabla.estado}">Estado</th>
<th scope="col" th:text="#{usuarios.tabla.acciones}">Acciones</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
</th:block>
<th:block layout:fragment="modal" />
<th:block th:replace="~{theme/partials/vendor-scripts :: scripts}" />
<th:block layout:fragment="pagejs">
<script th:src="@{/assets/libs/datatables/datatables.min.js}"></script>
<script th:src="@{/assets/libs/datatables/dataTables.bootstrap5.min.js}"></script>
<script th:src="@{/assets/js/pages/imprimelibros/users/list.js}"></script>
</th:block>
</body>
</html>