remove extensions

This commit is contained in:
srgooglo 2022-05-30 22:08:29 +02:00
parent 7d98769806
commit 27f6480be4
14 changed files with 0 additions and 1356 deletions

View File

@ -1,179 +0,0 @@
import { Extension } from "evite"
import config from "config"
import { Bridge } from "linebridge/dist/client"
import { Session } from "models"
export default class ApiExtension extends Extension {
depends = ["SettingsExtension"]
constructor(app, main) {
super(app, main)
//this.config = this.getServerOrigins()
this.apiBridge = this.createBridge()
this.WSInterface = this.apiBridge.wsInterface
this.WSInterface.request = this.WSRequest
this.WSInterface.listen = this.handleWSListener
this.WSSockets = this.WSInterface.sockets
this.WSInterface.mainSocketConnected = false
}
getServerOrigins = () => {
// TODO: try to get origins from settings
// const storagedOrigins = window.app.settings.get("serverOrigins")
}
initializers = [
async () => {
this.WSSockets.main.on("authenticated", () => {
console.debug("[WS] Authenticated")
})
this.WSSockets.main.on("authenticateFailed", (error) => {
console.error("[WS] Authenticate Failed", error)
})
this.WSSockets.main.on("connect", () => {
window.app.eventBus.emit("websocket_connected")
this.WSInterface.mainSocketConnected = true
})
this.WSSockets.main.on("disconnect", (...context) => {
window.app.eventBus.emit("websocket_disconnected", ...context)
this.WSInterface.mainSocketConnected = false
})
this.WSSockets.main.on("connect_error", (...context) => {
window.app.eventBus.emit("websocket_connection_error", ...context)
this.WSInterface.mainSocketConnected = false
})
this.mainContext.setToWindowContext("api", this.apiBridge)
this.mainContext.setToWindowContext("ws", this.WSInterface)
this.mainContext.setToWindowContext("request", this.apiBridge.endpoints)
this.mainContext.setToWindowContext("WSRequest", this.WSInterface.wsEndpoints)
}
]
createBridge() {
const getSessionContext = async () => {
const obj = {}
const token = await Session.token
if (token) {
// append token to context
obj.headers = {
Authorization: `Bearer ${token ?? null}`,
}
}
return obj
}
const handleResponse = async (data) => {
// handle token regeneration
if (data.headers?.regenerated_token) {
Session.token = data.headers.regenerated_token
console.debug("[REGENERATION] New token generated")
}
// handle 401 responses
if (data instanceof Error) {
if (data.response.status === 401) {
window.app.eventBus.emit("invalid_session")
}
}
}
return new Bridge({
origin: config.remotes.mainApi,
wsOrigin: config.remotes.websocketApi,
wsOptions: {
autoConnect: false,
},
onRequest: getSessionContext,
onResponse: handleResponse,
})
}
async attachWSConnection() {
if (!this.WSInterface.sockets.main.connected) {
await this.WSInterface.sockets.main.connect()
}
let startTime = null
let latency = null
let latencyWarning = false
let pingInterval = setInterval(() => {
if (!this.WSInterface.mainSocketConnected) {
return clearTimeout(pingInterval)
}
startTime = Date.now()
this.WSInterface.sockets.main.emit("ping")
}, 2000)
this.WSInterface.sockets.main.on("pong", () => {
latency = Date.now() - startTime
if (latency > 800 && this.WSInterface.mainSocketConnected) {
latencyWarning = true
console.error("[WS] Latency is too high > 800ms", latency)
window.app.eventBus.emit("websocket_latency_too_high", latency)
} else if (latencyWarning && this.WSInterface.mainSocketConnected) {
latencyWarning = false
window.app.eventBus.emit("websocket_latency_normal", latency)
}
})
}
async attachAPIConnection() {
await this.apiBridge.initialize()
}
handleWSListener = (to, fn) => {
if (typeof to === "undefined") {
console.error("handleWSListener: to must be defined")
return false
}
if (typeof fn !== "function") {
console.error("handleWSListener: fn must be function")
return false
}
let ns = "main"
let event = null
if (typeof to === "string") {
event = to
} else if (typeof to === "object") {
ns = to.ns
event = to.event
}
return window.app.ws.sockets[ns].on(event, async (...context) => {
return await fn(...context)
})
}
WSRequest = (socket = "main", channel, ...args) => {
return new Promise(async (resolve, reject) => {
const request = await window.app.ws.sockets[socket].emit(channel, ...args)
request.on("responseError", (...errors) => {
return reject(...errors)
})
request.on("response", (...responses) => {
return resolve(...responses)
})
})
}
window = {
ApiController: this
}
}

View File

@ -1,129 +0,0 @@
import { Extension } from "evite"
import React from "react"
import { Window } from "components"
import { Skeleton, Tabs } from "antd"
class DebuggerUI extends React.Component {
state = {
loading: true,
error: null,
debuggers: null,
active: null,
}
toogleLoading = (to = !this.state.loading ?? false) => {
this.setState({ loading: to })
}
loadDebuggers = async () => {
this.toogleLoading(true)
const debuggers = await import(`~/debugComponents`)
let renders = {}
Object.keys(debuggers).forEach((key) => {
renders[key] = debuggers[key]
})
this.setState({ debuggers: renders }, () => {
this.toogleLoading(false)
})
}
componentDidMount = async () => {
await this.loadDebuggers()
}
componentDidCatch = (error, info) => {
this.setState({ error })
}
onChangeTab = (key) => {
console.debug(`Changing tab to ${key}`)
this.setState({ active: key, error: null })
}
renderError = (key, error) => {
return (
<div>
<h2>Debugger Error</h2>
<i>
<h4>
Catch on [<strong>{key}</strong>]
</h4>
</i>
`<code>{error.message}</code>`
<hr />
<code>{error.stack}</code>
</div>
)
}
renderTabs = () => {
return Object.keys(this.state.debuggers).map((key) => {
return <Tabs.TabPane tab={key} key={key} />
})
}
renderDebugger = (_debugger) => {
try {
return React.createElement(window.app.bindContexts(_debugger))
} catch (error) {
return this.renderError(key, error)
}
}
render() {
const { loading, error } = this.state
if (loading) {
return <Skeleton active />
}
return (
<div>
<Tabs
onChange={this.onChangeTab}
activeKey={this.state.active}
>
{this.renderTabs()}
</Tabs>
{error && this.renderError(this.state.active, error)}
{!this.state.active ? (
<div> Select an debugger to start </div>
) : (
this.renderDebugger(this.state.debuggers[this.state.active])
)}
</div>
)
}
}
class Debugger {
constructor(mainContext, params = {}) {
this.mainContext = mainContext
this.params = { ...params }
this.bindings = {}
}
openWindow = () => {
new Window.DOMWindow({ id: "debugger", children: window.app.bindContexts(DebuggerUI) }).create()
}
bind = (id, binding) => {
this.bindings[id] = binding
return binding
}
unbind = (id) => {
delete this.bindings[id]
}
}
export default class VisualDebugger extends Extension {
window = {
debug: new Debugger(this.mainContext)
}
}

View File

@ -1,73 +0,0 @@
import { Extension } from "evite"
import config from "config"
import i18n from "i18next"
import { initReactI18next } from "react-i18next"
export const SUPPORTED_LANGUAGES = config.i18n?.languages ?? {}
export const SUPPORTED_LOCALES = SUPPORTED_LANGUAGES.map((l) => l.locale)
export const DEFAULT_LOCALE = config.i18n?.defaultLocale
export function extractLocaleFromPath(path = "") {
const [_, maybeLocale] = path.split("/")
return SUPPORTED_LOCALES.includes(maybeLocale) ? maybeLocale : DEFAULT_LOCALE
}
const messageImports = import.meta.glob("./translations/*.json")
export default class I18nExtension extends Extension {
depends = ["SettingsExtension"]
importLocale = async (locale) => {
const [, importLocale] =
Object.entries(messageImports).find(([key]) =>
key.includes(`/${locale}.`)
) || []
return importLocale && importLocale()
}
loadAsyncLanguage = async function (locale) {
locale = locale ?? DEFAULT_LOCALE
try {
const result = await this.importLocale(locale)
if (result) {
i18n.addResourceBundle(locale, "translation", result.default || result)
i18n.changeLanguage(locale)
}
} catch (error) {
console.error(error)
}
}
initializers = [
async () => {
let locale = app.settings.get("language") ?? DEFAULT_LOCALE
if (!SUPPORTED_LOCALES.includes(locale)) {
locale = DEFAULT_LOCALE
}
const messages = await this.importLocale(locale)
i18n
.use(initReactI18next) // passes i18n down to react-i18next
.init({
// debug: true,
resources: {
[locale]: { translation: messages.default || messages },
},
lng: locale,
//fallbackLng: DEFAULT_LOCALE,
interpolation: {
escapeValue: false, // react already safes from xss
},
})
this.mainContext.eventBus.on("changeLanguage", (locale) => {
this.loadAsyncLanguage(locale)
})
},
]
}

View File

@ -1,74 +0,0 @@
import { Extension } from "evite"
import React from "react"
import { notification as Notf } from "antd"
import { Icons, createIconRender } from "components/Icons"
import { Translation } from "react-i18next"
import { Haptics } from "@capacitor/haptics"
export default class NotificationController extends Extension {
getSoundVolume = () => {
return (window.app.settings.get("notifications_sound_volume") ?? 50) / 100
}
new = (notification, options = {}) => {
this.notify(notification, options)
this.playHaptic(options)
this.playAudio(options)
}
notify = (notification, options = {}) => {
if (typeof notification === "string") {
notification = {
title: "New notification",
description: notification
}
}
Notf.open({
message: <Translation>
{(t) => t(notification.title)}
</Translation>,
description: <Translation>
{(t) => t(notification.description)}
</Translation>,
duration: notification.duration ?? 4,
icon: React.isValidElement(notification.icon) ? notification.icon : (createIconRender(notification.icon) ?? <Icons.Bell />),
})
}
playHaptic = async (options = {}) => {
const vibrationEnabled = options.vibrationEnabled ?? window.app.settings.get("notifications_vibrate")
if (vibrationEnabled) {
await Haptics.vibrate()
}
}
playAudio = (options = {}) => {
const soundEnabled = options.soundEnabled ?? window.app.settings.get("notifications_sound")
const soundVolume = options.soundVolume ? options.soundVolume / 100 : this.getSoundVolume()
if (soundEnabled) {
window.app.SoundEngine.play("notification", {
volume: soundVolume,
})
}
}
initializers = [
function () {
this.eventBus.on("changeNotificationsSoundVolume", (value) => {
app.notifications.playAudio({ soundVolume: value })
})
this.eventBus.on("changeNotificationsVibrate", (value) => {
app.notifications.playHaptic({
vibrationEnabled: value,
})
})
}
]
window = {
notifications: this
}
}

View File

@ -1,194 +0,0 @@
import React from "react"
import { EvitePureComponent, Extension } from "evite"
import progressBar from "nprogress"
import routes from "virtual:generated-pages"
import NotFoundRender from "./staticsRenders/404"
import CrashRender from "./staticsRenders/crash"
export const ConnectWithApp = (component) => {
return window.app.bindContexts(component)
}
export function GetRoutesComponentMap() {
return routes.reduce((acc, route) => {
const { path, component } = route
acc[path] = component
return acc
}, {})
}
export class RouteRender extends EvitePureComponent {
state = {
renderInitialization: true,
renderComponent: null,
renderError: null,
//pageStatement: new PageStatement(),
routes: GetRoutesComponentMap() ?? {},
crash: null,
}
handleBusEvents = {
"app.render_initialization": () => {
this.setState({ renderInitialization: true })
},
"app.render_initialization_done": () => {
this.setState({ renderInitialization: false })
},
"app.crash": (message, error) => {
this.setState({ crash: { message, error } })
},
"locationChange": (event) => {
this.loadRender()
},
}
componentDidMount() {
this._ismounted = true
this._loadBusEvents()
this.loadRender()
}
componentWillUnmount() {
this._ismounted = false
this._unloadBusEvents()
}
loadRender = (path) => {
if (!this._ismounted) {
console.warn("RouteRender is not mounted, skipping render load")
return false
}
let componentModule = this.state.routes[path ?? this.props.path ?? window.location.pathname] ?? this.props.staticRenders?.NotFound ?? NotFoundRender
// TODO: in a future use, we can use `pageStatement` class for managing statement
window.app.pageStatement = Object.freeze(componentModule.pageStatement) ?? Object.freeze({})
return this.setState({ renderComponent: componentModule })
}
componentDidCatch(info, stack) {
this.setState({ renderError: { info, stack } })
}
render() {
if (this.state.crash) {
const StaticCrashRender = this.props.staticRenders?.Crash ?? CrashRender
return <StaticCrashRender crash={this.state.crash} />
}
if (this.state.renderError) {
if (this.props.staticRenders?.RenderError) {
return React.createElement(this.props.staticRenders?.RenderError, { error: this.state.renderError })
}
return JSON.stringify(this.state.renderError)
}
if (this.state.renderInitialization) {
const StaticInitializationRender = this.props.staticRenders?.initialization ?? null
return <StaticInitializationRender />
}
if (!this.state.renderComponent) {
return null
}
return React.createElement(ConnectWithApp(this.state.renderComponent), this.props)
}
}
export class RenderExtension extends Extension {
initializers = [
async function () {
const defaultTransitionDelay = 150
this.progressBar = progressBar.configure({ parent: "html", showSpinner: false })
this.history.listen((event) => {
this.eventBus.emit("transitionDone", event)
this.eventBus.emit("locationChange", event)
this.progressBar.done()
})
this.history.setLocation = (to, state, delay) => {
const lastLocation = this.history.lastLocation
if (typeof lastLocation !== "undefined" && lastLocation?.pathname === to && lastLocation?.state === state) {
return false
}
this.progressBar.start()
this.eventBus.emit("transitionStart", delay)
setTimeout(() => {
this.history.push({
pathname: to,
}, state)
this.history.lastLocation = this.history.location
}, delay ?? defaultTransitionDelay)
}
this.setToWindowContext("setLocation", this.history.setLocation)
},
]
expose = {
validateLocationSlash: (location) => {
let key = location ?? window.location.pathname
while (key[0] === "/") {
key = key.slice(1, key.length)
}
return key
},
}
window = {
isAppCapacitor: () => window.navigator.userAgent === "capacitor",
bindContexts: (component) => {
let contexts = {
main: {},
app: {},
}
if (typeof component.bindApp === "string") {
if (component.bindApp === "all") {
Object.keys(app).forEach((key) => {
contexts.app[key] = app[key]
})
}
} else {
if (Array.isArray(component.bindApp)) {
component.bindApp.forEach((key) => {
contexts.app[key] = app[key]
})
}
}
if (typeof component.bindMain === "string") {
if (component.bindMain === "all") {
Object.keys(main).forEach((key) => {
contexts.main[key] = main[key]
})
}
} else {
if (Array.isArray(component.bindMain)) {
component.bindMain.forEach((key) => {
contexts.main[key] = main[key]
})
}
}
return (props) => React.createElement(component, { ...props, contexts })
},
}
}
export default RenderExtension

View File

@ -1,76 +0,0 @@
import { Extension } from "evite"
import store from "store"
import defaultSettings from "schemas/defaultSettings.json"
import { Observable } from "rxjs"
export default class SettingsExtension extends Extension {
constructor(app, main) {
super(app, main)
this.storeKey = "app_settings"
this.settings = store.get(this.storeKey) ?? {}
this._setDefaultUndefined()
}
_setDefaultUndefined = () => {
Object.keys(defaultSettings).forEach((key) => {
const value = defaultSettings[key]
// Only set default if value is undefined
if (typeof this.settings[key] === "undefined") {
this.settings[key] = value
}
})
}
defaults = (key) => {
if (typeof key === "undefined") {
return defaultSettings
}
return defaultSettings[key]
}
is = (key, value) => {
return this.settings[key] === value
}
set = (key, value) => {
this.settings[key] = value
store.set(this.storeKey, this.settings)
window.app.eventBus.emit("setting.update", { key, value })
window.app.eventBus.emit(`setting.update.${key}`, value)
return this.settings
}
get = (key) => {
if (typeof key === "undefined") {
return this.settings
}
return this.settings[key]
}
withEvent = (listenEvent, defaultValue) => {
let value = defaultValue ?? this.settings[key] ?? false
const observable = new Observable((subscriber) => {
subscriber.next(value)
window.app.eventBus.on(listenEvent, (to) => {
value = to
subscriber.next(value)
})
})
return observable.subscribe((value) => {
return value
})
}
window = {
"settings": this
}
}

View File

@ -1,70 +0,0 @@
import { Extension } from "evite"
export default class ShortcutsExtension extends Extension {
constructor(app, main) {
super(app, main)
this.shortcuts = {}
document.addEventListener("keydown", (event) => {
// FIXME: event.key sometimes is not defined
const key = event.key.toLowerCase()
const shortcut = this.shortcuts[key]
if (shortcut) {
if (typeof shortcut.ctrl === "boolean" && event.ctrlKey !== shortcut.ctrl) {
return
}
if (typeof shortcut.shift === "boolean" && event.shiftKey !== shortcut.shift) {
return
}
if (typeof shortcut.alt === "boolean" && event.altKey !== shortcut.alt) {
return
}
if (typeof shortcut.meta === "boolean" && event.metaKey !== shortcut.meta) {
return
}
if (shortcut.preventDefault) {
event.preventDefault()
}
if (typeof shortcut.fn === "function") {
shortcut.fn()
}
}
})
}
register = (keybind = {}, fn) => {
if (typeof keybind === "string") {
keybind = {
key: keybind,
}
}
this.shortcuts[keybind.key] = {
...keybind,
fn,
}
}
remove = (array) => {
if (typeof array === "string") {
array = [array]
}
array.forEach(key => {
delete this.shortcuts[key]
})
}
window = {
ShortcutsController: this
}
}

View File

@ -1,43 +0,0 @@
import { Extension } from "evite"
import { Howl } from "howler"
import config from "config"
export default class SoundEngineExtension extends Extension {
sounds = {}
getSounds = async () => {
// TODO: Load custom soundpacks manifests
let soundPack = config.defaultSoundPack ?? {}
Object.keys(soundPack).forEach((key) => {
const src = soundPack[key]
soundPack[key] = (options) => new Howl({
volume: window.app.settings.get("generalAudioVolume") ?? 0.5,
...options,
src: [src],
})
})
return soundPack
}
play = (name, options) => {
if (this.sounds[name]) {
return this.sounds[name](options).play()
} else {
console.error(`Sound ${name} not found.`)
return false
}
}
initializers = [
async () => {
this.sounds = await this.getSounds()
}
]
window = {
SoundEngine: this
}
}

View File

@ -1,7 +0,0 @@
import React from 'react'
export default () => {
return <div>
Not Found
</div>
}

View File

@ -1,15 +0,0 @@
import React from "react"
import "./index.less"
export default (props) => {
return <div className="app_crash">
<div className="header">
<h1>Crash</h1>
</div>
<h2>{props.crash.message}</h2>
<pre>{props.crash.error}</pre>
<div className="actions">
<button onClick={() => window.location.reload()}>Reload</button>
</div>
</div>
}

View File

@ -1,27 +0,0 @@
.app_crash {
position: absolute;
z-index: 9999;
top: 0;
right: 0;
width: 100vw;
height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.header {
display: flex;
text-align: center;
flex-direction: column;
justify-content: center;
svg {
width: 100px;
height: 100px;
}
}
}

View File

@ -1,152 +0,0 @@
import { Extension } from "evite"
import config from "config"
import store from "store"
import { ConfigProvider } from "antd"
export default class ThemeExtension extends Extension {
constructor(app, main) {
super(app, main)
this.themeManifestStorageKey = "theme"
this.modificationStorageKey = "themeModifications"
this.theme = null
this.mutation = null
this.currentVariant = null
}
initializers = [
async () => {
this.mainContext.eventBus.on("theme.applyVariant", (value) => {
this.applyVariant(value)
this.setVariant(value)
})
this.mainContext.eventBus.on("modifyTheme", (value) => {
this.update(value)
this.setModifications(this.mutation)
})
this.mainContext.eventBus.on("resetTheme", () => {
this.resetDefault()
})
await this.initialize()
},
]
static get currentVariant() {
return document.documentElement.style.getPropertyValue("--themeVariant")
}
initialize = async () => {
let theme = this.getStoragedTheme()
const modifications = this.getStoragedModifications()
const variantKey = this.getStoragedVariant()
if (!theme) {
// load default theme
theme = this.getDefaultTheme()
} else {
// load URL and initialize theme
}
// set global theme
this.theme = theme
// override with static vars
if (theme.staticVars) {
this.update(theme.staticVars)
}
// override theme with modifications
if (modifications) {
this.update(modifications)
}
// apply variation
this.applyVariant(variantKey)
}
getRootVariables = () => {
let attributes = document.documentElement.getAttribute("style").trim().split(";")
attributes = attributes.slice(0, (attributes.length - 1))
attributes = attributes.map((variable) => {
let [key, value] = variable.split(":")
key = key.split("--")[1]
return [key, value]
})
return Object.fromEntries(attributes)
}
getDefaultTheme = () => {
// TODO: Use evite CONSTANTS_API
return config.defaultTheme
}
getStoragedTheme = () => {
return store.get(this.themeManifestStorageKey)
}
getStoragedModifications = () => {
return store.get(this.modificationStorageKey)
}
getStoragedVariant = () => {
return app.settings.get("themeVariant")
}
setVariant = (variationKey) => {
return app.settings.set("themeVariant", variationKey)
}
setModifications = (modifications) => {
return store.set(this.modificationStorageKey, modifications)
}
resetDefault = () => {
store.remove(this.themeManifestStorageKey)
store.remove(this.modificationStorageKey)
window.app.settings.set("primaryColor", this.theme.staticVars.primaryColor)
this.initialize()
}
update = (update) => {
if (typeof update !== "object") {
return false
}
this.mutation = {
...this.theme.staticVars,
...this.mutation,
...update
}
Object.keys(this.mutation).forEach(key => {
document.documentElement.style.setProperty(`--${key}`, this.mutation[key])
})
document.documentElement.className = `theme-${this.currentVariant}`
document.documentElement.style.setProperty(`--themeVariant`, this.currentVariant)
ConfigProvider.config({ theme: this.mutation })
}
applyVariant = (variant = (this.theme.defaultVariant ?? "light")) => {
const values = this.theme.variants[variant]
if (values) {
this.currentVariant = variant
this.update(values)
}
}
window = {
ThemeController: this
}
}

View File

@ -1,103 +0,0 @@
{
"main_welcome": "Welcome back,",
"assigned_for_you": "Assigned for you",
"no_assigned_workorders": "No assigned workorders",
"new": "New",
"close": "Close",
"done": "Done",
"edit": "Edit",
"save": "Save",
"cancel": "Cancel",
"delete": "Delete",
"import": "Import",
"export": "Export",
"refresh": "Refresh",
"reload": "Reload",
"search": "Search",
"status": "Status",
"type": "Type",
"about": "About",
"current": "Current",
"statistics": "Statistics",
"name": "Name",
"username": "Username",
"email": "Email",
"password": "Password",
"sessions": "Sessions",
"compact_view": "Compact view",
"sign_in": "Sign in",
"sign_out": "Sign out",
"sign_up": "Sign up",
"all_sessions": "All sessions",
"destroy_all_sessions": "Destroy all sessions",
"account_info": "Account info",
"password_confirmation": "Password confirmation",
"new_product": "New product",
"description": "Description",
"describe_something": "Describe something",
"operations": "Operations",
"select_operation": "Select operation",
"select_operations": "Select operations",
"tasks": "Tasks",
"select_task": "Select task",
"select_tasks": "Select tasks",
"add_task": "Add task",
"add_tasks": "Add tasks",
"location": "Location",
"select_location": "Select location",
"select_locations": "Select locations",
"add_location": "Add location",
"add_locations": "Add locations",
"materials": "Materials",
"select_material": "Select material",
"select_materials": "Select materials",
"add_material": "Add material",
"add_materials": "Add materials",
"quantity": "Quantity",
"select_quantity": "Select quantity",
"select_quantities": "Select quantities",
"add_quantity": "Add quantity",
"add_quantities": "Add quantities",
"units": "Units",
"select_unit": "Select unit",
"select_units": "Select units",
"add_unit": "Add unit",
"add_units": "Add units",
"suppliers": "Suppliers",
"select_supplier": "Select supplier",
"select_suppliers": "Select suppliers",
"add_supplier": "Add supplier",
"add_suppliers": "Add suppliers",
"customers": "Customers",
"select_customer": "Select customer",
"select_customers": "Select customers",
"add_customer": "Add customer",
"add_customers": "Add customers",
"employees": "Employees",
"select_employee": "Select employee",
"select_employees": "Select employees",
"add_employee": "Add employee",
"add_employees": "Add employees",
"equipment": "Equipment",
"select_equipment": "Select equipment",
"select": "Select",
"variants": "Variants",
"select_variant": "Select variant",
"select_variants": "Select variants",
"settins_group_general": "General",
"settings_general_language": "Language",
"settings_general_language_description": "Choose language for using in application.",
"settings_general_sidebarAutoCollapse": "Sidebar auto collapse",
"settings_general_sidebarAutoCollapse_description": "Collapse sidebar when loose focus.",
"settings_group_aspect": "Aspect",
"settings_aspect_reduceAnimations": "Reduce animations",
"settings_aspect_reduceAnimations_description": "Reduce animation of the application.",
"settings_aspect_darkMode": "Dark mode",
"settings_aspect_darkMode_description": "Enable dark mode for the application.",
"settings_aspect_primaryColor": "Primary color",
"settings_aspect_primaryColor_description": "Change primary color of the application.",
"settings_aspect_resetTheme": "Reset theme",
"settings_aspect_resetTheme_description": "Reset theme to default."
}

View File

@ -1,214 +0,0 @@
{
"Dashboard": "Inicio",
"main_welcome": "Bienvenido,",
"assigned_for_you": "Asignado para usted",
"no_assigned_workorders": "No hay trabajos asignados",
"Start": "Iniciar",
"End": "Finalizar",
"Stop": "Parar",
"Started": "Iniciado",
"started": "iniciado",
"Ended": "Finalizado",
"ended": "finalizado",
"Expired": "Expirado",
"expired": "expirado",
"Stopped": "Parado",
"stopped": "parado",
"Pending": "Pendiente",
"pending": "pendiente",
"Finished": "Finalizado",
"finished": "terminado",
"Cancelled": "Cancelado",
"cancelled": "cancelado",
"Assigned": "Asignado",
"assigned": "asignado",
"Ready": "Listo",
"ready": "listo",
"No description": "Sin descripción",
"All": "Todos",
"all": "todos",
"or": "o",
"Browse": "Buscar",
"Create new": "Crear nuevo",
"New": "Nuevo",
"Close": "Cerrar",
"Done": "Listo",
"Next": "Siguiente",
"Previous": "Anterior",
"Schedule": "Plazo",
"Edit": "Modificar",
"Save": "Guardar",
"Cancel": "Cancelar",
"Delete": "Eliminar",
"State": "Estado",
"Modify": "Modificar",
"modify": "modificar",
"Notifications": "Notificaciones",
"Notification": "Notificación",
"Haptic": "Vibración",
"Haptic Feedback": "Vibración de respuesta",
"Enable haptic feedback on touch events.": "Habilitar vibración de respuesta cuando exista un evento de toque.",
"Selection press delay": "Retraso de presión de selección",
"Set the delay before the selection trigger is activated.": "Establecer el retraso antes de que el disparador de selección sea activado.",
"Force Mobile Mode": "Forzar modo móvil",
"Force the application to run in mobile mode.": "Forzar la aplicación a ejecutarse en modo móvil.",
"Manage operators": "Administrar operadores",
"Manage users": "Administrar usuarios",
"Manage groups": "Administrar grupos",
"Manage workflows": "Administrar flujos de trabajo",
"Manage roles": "Administrar roles",
"Manage permissions": "Administrar permisos",
"Disable": "Deshabilitar",
"Disabled": "Deshabilitado",
"Discard": "Descartar",
"Unselect all": "Deseleccionar todo",
"Select all": "Seleccionar todo",
"Add commit": "Añadir registro",
"Commit": "Registrar",
"Commits": "Registros",
"Assistant mode": "Modo asistente",
"View finished": "Ver terminados",
"View pending": "Ver pendientes",
"View assigned": "Ver asignados",
"View ready": "Ver listos",
"View cancelled": "Ver cancelados",
"View all": "Ver todos",
"View": "Ver",
"Mark produced quantity": "Marcar cantidad producida",
"Mark remaining amount": "Marcar cantidad restante",
"Quantity": "Cantidad",
"Quantity produced": "Cantidad producida",
"Quantity left": "Cantidad restante",
"Production target": "Objectivo de producción",
"Section": "Sección",
"Sections": "Secciones",
"Workshift": "Turno",
"workshift": "turno",
"Workshifts": "Turnos",
"workshifts": "turnos",
"Operation": "Operación",
"Operations": "Operaciones",
"Stock Target": "Stock objetivo",
"Vault item": "Artículo de bóveda",
"Stock item": "Artículo de stock",
"Vault": "Bóveda",
"Phase": "Fase",
"Variants": "Variantes",
"Variant": "Variante",
"Description": "Descripción",
"Task": "Tarea",
"Tasks": "Tareas",
"Product": "Producto",
"Products": "Productos",
"Operator": "Operador",
"Operators": "Operadores",
"Workload": "Carga de trabajo",
"workload": "carga de trabajo",
"Workloads": "Cargas de trabajo",
"workloads": "cargas de trabajo",
"Workorder": "Orden de trabajo",
"workorder": "orden de trabajo",
"Workorders": "Ordenes de trabajo",
"workorders": "ordenes de trabajo",
"Workpart": "Parte de trabajo",
"workpart": "parte de trabajo",
"Workparts": "Partes de trabajo",
"workparts": "parte de trabajo",
"Payload": "Carga",
"payload": "carga",
"Payloads": "Cargas",
"payloads": "carga",
"Commit all": "Registrar todo",
"Mark quantity": "Marcar cantidad",
"Mark": "Marcar",
"Marked": "Marcado",
"Marked quantity": "Cantidad marcada",
"Marked amount": "Cantidad marcada",
"Marked amount left": "Cantidad restante marcada",
"Marked amount produced": "Cantidad producida marcada",
"Marked amount remaining": "Cantidad restante marcada",
"Marked amount target": "Cantidad objetivo marcada",
"Marked amount stock": "Cantidad stock marcada",
"Notifications Sound": "Sonido de notificación",
"Play a sound when a notification is received.": "Reproducir un sonido cuando se recibe una notificación.",
"Vibration": "Vibración",
"Vibrate the device when a notification is received.": "Vibrar el dispositivo cuando se recibe una notificación.",
"Sound Volume": "Volumen de sonido",
"Set the volume of the sound when a notification is received.": "Establecer el volumen del sonido cuando se recibe una notificación.",
"Workorder Notifications": "Notificaciones de orden de trabajo",
"Display in-app notifications for workorders updates.": "Mostrar notificaciones para las actualizaciones de las ordenes de trabajo.",
"Accounts": "Cuentas",
"Import": "Importar",
"Export": "Exportar",
"Refresh": "Actualizar",
"Reload": "Recargar",
"Required": "Requerido",
"Optional": "Opcional",
"Search": "Buscar",
"Status": "Estado",
"Type": "Tipo",
"About": "Acerca de",
"Current": "Actual",
"Statistics": "Estadísticas",
"Name": "Nombre",
"Users": "Usuarios",
"Username": "Nombre de usuario",
"Settings": "Configuración",
"Email": "Correo electrónico",
"Password": "Contraseña",
"Sessions": "Sesiones",
"Compact view": "Vista compacta",
"Add to catalog": "Añadir al catálogo",
"Fabric": "Fabric",
"Press and hold for 2 seconds to toogle running": "Pulse y mantenga pulsado durante 2 segundos para alternar el funcionamiento",
"Production quantity already has been reached": "La cantidad de producción ya ha sido alcanzada",
"Production quantity is not enough": "La cantidad de producción no es suficiente",
"Are you sure you want to commit for this workpart?": "¿Está seguro de que desea consolidar esta parte de trabajo?",
"Are you sure you want to commit all quantity left?": "¿Está seguro de que desea consolidar toda la cantidad restante?",
"This will commit all quantity left and finish the production for this workload.": "Esto consolidará toda la cantidad restante y terminará la producción para esta carga de trabajo.",
"Are you sure you want to commit for this workorder?": "¿Está seguro de que desea consolidar esta orden de trabajo?",
"Enter the name or a reference for the workorder.": "Introduzca el nombre o una referencia para la orden de trabajo.",
"Select the section where the workorder will be deployed.": "Seleccione la sección donde se desplegará la orden de trabajo.",
"Select the schedule for the workorder.": "Seleccione el plazo para la orden de trabajo.",
"Assign the operators for the workorder.": "Asigne los operadores para la orden de trabajo.",
"Define the payloads for the workorder.": "Defina las cargas para la orden de trabajo.",
"Define the workloads for the workorder.": "Defina las cargas de trabajo para la orden de trabajo.",
"Leaving process running on background, dont forget to stop it when you are done": "Dejando el proceso en ejecución en segundo plano, no olvide detenerlo cuando haya terminado",
"Task remains opened, dont forget to stop it when you are done": "La tarea permanece abierta, no olvide detenerla cuando haya terminado",
"Select a option": "Seleccione una opción",
"Set the quantity produced": "Marque la cantidad producida",
"Experimental": "Experimental",
"New workorder assigned": "Nueva orden de trabajo asignada",
"Check the new list of workorder": "Compruebe la nueva lista de ordenes de trabajo",
"Do you want to delete these items?": "¿Desea eliminar estos elementos?",
"This action cannot be undone, and will permanently delete the selected items.": "Esta acción no se puede deshacer, y eliminará permanentemente los elementos seleccionados.",
"Assigned operators": "Operadores asignados",
"Assigments": "Asignaciones",
"Working Tasks": "Tareas en ejecución",
"You are not working on any task": "No estás trabajando en ninguna tarea",
"Update": "Actualizar",
"Update status": "Actualizar estado",
"Archived": "Archivado",
"archived": "archivado",
"Archive": "Archivar",
"archive": "archivar",
"General": "General",
"Sidebar": "Barra lateral",
"Aspect": "Aspecto",
"Language": "Idioma",
"Choose a language for the application": "Elige un idioma para la aplicación.",
"Edit Sidebar": "Editar barra lateral",
"Auto Collapse": "Auto colapsar",
"Collapse the sidebar when loose focus": "Colapsar la barra lateral cuando pierda el foco.",
"Reduce animation": "Reducir animación",
"Primary color": "Color primario",
"Change primary color of the application.": "Cambia el color primario de la aplicación.",
"Dark mode": "Modo oscuro",
"Images": "Imágenes",
"Add others": "Añadir otros",
"Export tokens": "Exportar bonos de trabajo",
"Description of the task. It should be a general description of the product. Do not include information that may vary. e.g. 'The product is a white shirt with a elastic red collar, size M'": "Descripción de la tarea. Debe ser una descripción general del producto. No incluya información que pueda variar. Por ejemplo, 'El producto es una camisa blanca con un collar de color rojo, tamaño M'",
"Define variants for this item. Only the types of variations that may exist of a product should be included. e.g. Size, Color, Material, etc.": "Defina las variantes para este artículo. Sólo deben incluirse los tipos de variaciones que pueden existir de un producto. Por ejemplo, Tamaño, Color, Material, etc.",
"Append some images to describe this item.": "Agregue algunas imágenes para describir este artículo."
}