avo 1.3.1 → 1.3.5
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of avo might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/Gemfile.lock +2 -2
- data/app/components/avo/common/key_value_component.html.erb +53 -0
- data/app/components/avo/common/key_value_component.rb +11 -0
- data/app/components/avo/edit/fields/key_value_field_component.html.erb +3 -0
- data/app/components/avo/edit/fields/key_value_field_component.rb +4 -0
- data/app/components/avo/edit/fields/trix_field_component.html.erb +1 -1
- data/app/components/avo/show/fields/key_value_field_component.html.erb +3 -0
- data/app/components/avo/show/fields/key_value_field_component.rb +4 -0
- data/app/helpers/avo/application_helper.rb +1 -1
- data/app/packs/entrypoints/application.js +14 -10
- data/app/packs/js/controllers/fields/code_field_controller.js +1 -0
- data/app/packs/js/controllers/fields/key_value_controller.js +137 -0
- data/lib/avo.rb +1 -1
- data/lib/avo/fields/key_value_field.rb +24 -1
- data/lib/avo/version.rb +1 -1
- data/lib/generators/avo/action_generator.rb +1 -1
- data/lib/generators/avo/locales_generator.rb +2 -2
- data/lib/generators/avo/templates/action.tt +5 -9
- data/lib/generators/avo/templates/locales/avo.en.yml +1 -0
- data/lib/generators/avo/templates/locales/avo.nb-NO.yml +81 -0
- data/lib/generators/avo/templates/locales/avo.pt-BR.yml +82 -0
- data/lib/generators/avo/templates/locales/avo.ro.yml +70 -0
- data/public/avo-packs/css/{application-af3e670d.css → application-0b91a712.css} +85 -18
- data/public/avo-packs/css/application-0b91a712.css.br +0 -0
- data/public/avo-packs/css/application-0b91a712.css.gz +0 -0
- data/public/avo-packs/css/application-0b91a712.css.map +1 -0
- data/public/avo-packs/css/application-0b91a712.css.map.br +0 -0
- data/public/avo-packs/css/application-0b91a712.css.map.gz +0 -0
- data/public/avo-packs/js/application-c2a8a64ca8f5d2805d79.js +26 -0
- data/public/avo-packs/js/{application-801f1297670a4c6df1b6.js.LICENSE.txt → application-c2a8a64ca8f5d2805d79.js.LICENSE.txt} +0 -0
- data/public/avo-packs/js/application-c2a8a64ca8f5d2805d79.js.br +0 -0
- data/public/avo-packs/js/application-c2a8a64ca8f5d2805d79.js.gz +0 -0
- data/public/avo-packs/js/application-c2a8a64ca8f5d2805d79.js.map +1 -0
- data/public/avo-packs/js/application-c2a8a64ca8f5d2805d79.js.map.br +0 -0
- data/public/avo-packs/js/application-c2a8a64ca8f5d2805d79.js.map.gz +0 -0
- data/public/avo-packs/manifest.json +15 -15
- metadata +25 -15
- data/public/avo-packs/css/application-af3e670d.css.br +0 -0
- data/public/avo-packs/css/application-af3e670d.css.gz +0 -0
- data/public/avo-packs/css/application-af3e670d.css.map +0 -1
- data/public/avo-packs/css/application-af3e670d.css.map.br +0 -0
- data/public/avo-packs/css/application-af3e670d.css.map.gz +0 -0
- data/public/avo-packs/js/application-801f1297670a4c6df1b6.js +0 -26
- data/public/avo-packs/js/application-801f1297670a4c6df1b6.js.br +0 -0
- data/public/avo-packs/js/application-801f1297670a4c6df1b6.js.gz +0 -0
- data/public/avo-packs/js/application-801f1297670a4c6df1b6.js.map +0 -1
- data/public/avo-packs/js/application-801f1297670a4c6df1b6.js.map.br +0 -0
- data/public/avo-packs/js/application-801f1297670a4c6df1b6.js.map.gz +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f31ebc9caf8e281af2cb0e8ce4d0423ab4852f3475843af1d632e795930f5df0
|
4
|
+
data.tar.gz: 8117f6fca30c9f9f90ff61f5c7bdeb2908cb13fd731e3168c6678b5c4427f0a9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4d1deeabbc3538d4094312e9c08b384355882e55d1124976981e4e8f5356ed8d032f6a595261065a9fc567ca7529e639926f627e72231baf409709b2d19626d0
|
7
|
+
data.tar.gz: 036e731952aaf067ba2397fefa5d79a714332f39e7779a6586bee49e247c17ceb80f4e4226f4fa4cbb73be45c8d4573b09e5d4d7df29e921df1a767b980aca1e
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
avo (1.3.
|
4
|
+
avo (1.3.5)
|
5
5
|
active_link_to
|
6
6
|
addressable
|
7
7
|
breadcrumbs_on_rails
|
@@ -187,7 +187,7 @@ GEM
|
|
187
187
|
nokogiri (1.11.3-x86_64-linux)
|
188
188
|
racc (~> 1.4)
|
189
189
|
orm_adapter (0.5.0)
|
190
|
-
pagy (3.
|
190
|
+
pagy (3.13.0)
|
191
191
|
parallel (1.20.1)
|
192
192
|
parser (3.0.0.0)
|
193
193
|
ast (~> 2.4.1)
|
@@ -0,0 +1,53 @@
|
|
1
|
+
<div class="w-full shadow-lg rounded-lg overflow-hidden"
|
2
|
+
data-controller="key-value"
|
3
|
+
data-key-value-target="controller"
|
4
|
+
data-options="<%= @field.options.to_json %>"
|
5
|
+
data-input-classes="<%= input_classes %>"
|
6
|
+
data-editable="<%= @view.in?([:edit, :create]) %>"
|
7
|
+
>
|
8
|
+
<div class="w-full flex flex-col">
|
9
|
+
<div class="flex w-full">
|
10
|
+
<div class="flex w-full bg-gray-800 shadow overflow-hidden">
|
11
|
+
<div class="w-1/2 py-3 px-3 uppercase font-semibold text-xs text-white border-gray-600 border-r">
|
12
|
+
<%= @field.key_label %>
|
13
|
+
</div>
|
14
|
+
<div class="w-1/2 py-3 px-3 uppercase font-semibold text-xs text-white">
|
15
|
+
<%= @field.value_label %>
|
16
|
+
</div>
|
17
|
+
<% if @view.in?([:edit, :create]) %>
|
18
|
+
<div class="flex items-center justify-center p-2 px-3 border-l border-gray-600">
|
19
|
+
<a href="javascript:void(0);"
|
20
|
+
title="<%= @field.action_text %>"
|
21
|
+
data-tippy="tooltip"
|
22
|
+
data-button="add-row"
|
23
|
+
data-action="click->key-value#addRow"
|
24
|
+
<% if @field.disable_adding_rows %>
|
25
|
+
class="cursor-not-allowed"
|
26
|
+
<% end %>
|
27
|
+
>
|
28
|
+
<%= svg 'plus-circle', class: 'text-gray-400 h-5 hover:text-gray-500' %>
|
29
|
+
</a>
|
30
|
+
</div>
|
31
|
+
<% end %>
|
32
|
+
</div>
|
33
|
+
</div>
|
34
|
+
<div data-key-value-target="rows"></div>
|
35
|
+
</div>
|
36
|
+
<% if @form.present? %>
|
37
|
+
<%= @form.text_area @field.id,
|
38
|
+
value: @field.parsed_value,
|
39
|
+
class: 'hidden',
|
40
|
+
placeholder: @field.placeholder,
|
41
|
+
'data-key-value-target': 'input',
|
42
|
+
'data-view': :edit
|
43
|
+
%>
|
44
|
+
<% else %>
|
45
|
+
<%= text_area_tag @field.id,
|
46
|
+
@field.parsed_value,
|
47
|
+
class: 'hidden',
|
48
|
+
placeholder: @field.placeholder,
|
49
|
+
'data-key-value-target': 'input',
|
50
|
+
'data-view': :edit
|
51
|
+
%>
|
52
|
+
<% end %>
|
53
|
+
</div>
|
@@ -1,6 +1,6 @@
|
|
1
1
|
<%= edit_field_wrapper field: @field, index: @index, form: @form, resource: @resource, displayed_in_modal: @displayed_in_modal do %>
|
2
2
|
<% trix_id = "trix_#{@resource.name.underscore}_#{@field.id}" %>
|
3
|
-
<trix-editor input="<%= trix_id %>"
|
3
|
+
<trix-editor input="<%= trix_id %>" placeholder="<%= @field.placeholder %>"><%== @field.value %></trix-editor>
|
4
4
|
<%= @form.text_area @field.id,
|
5
5
|
id: trix_id,
|
6
6
|
class: helpers.input_classes('w-full hidden', has_error: (@resource.model.present? and @resource.model.errors.include?(@field.id))),
|
@@ -19,6 +19,19 @@ window.Turbolinks = Turbo
|
|
19
19
|
|
20
20
|
Mousetrap.bind('r r r', () => Turbo.visit(window.location.href, { action: 'replace' }))
|
21
21
|
|
22
|
+
function initTippy() {
|
23
|
+
tippy('[data-tippy="tooltip"]', {
|
24
|
+
theme: 'light',
|
25
|
+
content(reference) {
|
26
|
+
const title = reference.getAttribute('title')
|
27
|
+
reference.removeAttribute('title')
|
28
|
+
|
29
|
+
return title
|
30
|
+
},
|
31
|
+
})
|
32
|
+
}
|
33
|
+
window.initTippy = initTippy
|
34
|
+
|
22
35
|
const application = Application.start()
|
23
36
|
|
24
37
|
const context = require.context('./../js/controllers', true, /\.js$/)
|
@@ -29,16 +42,7 @@ application.load(definitionsFromContext(fieldsContext))
|
|
29
42
|
|
30
43
|
document.addEventListener('turbo:load', () => {
|
31
44
|
document.body.classList.remove('turbo-loading')
|
32
|
-
|
33
|
-
tippy('[data-tippy="tooltip"]', {
|
34
|
-
theme: 'light',
|
35
|
-
content(reference) {
|
36
|
-
const title = reference.getAttribute('title')
|
37
|
-
reference.removeAttribute('title')
|
38
|
-
|
39
|
-
return title
|
40
|
-
},
|
41
|
-
})
|
45
|
+
initTippy()
|
42
46
|
})
|
43
47
|
document.addEventListener('turbo:visit', () => document.body.classList.add('turbo-loading'))
|
44
48
|
document.addEventListener('turbo:submit-start', () => document.body.classList.add('turbo-loading'))
|
@@ -12,6 +12,7 @@ import 'codemirror/mode/shell/shell'
|
|
12
12
|
import 'codemirror/mode/sql/sql'
|
13
13
|
import 'codemirror/mode/vue/vue'
|
14
14
|
import 'codemirror/mode/xml/xml'
|
15
|
+
import 'codemirror/mode/yaml/yaml'
|
15
16
|
|
16
17
|
import { Controller } from 'stimulus'
|
17
18
|
import { castBoolean } from '@/js/helpers/cast_boolean'
|
@@ -0,0 +1,137 @@
|
|
1
|
+
/* eslint-disable max-len */
|
2
|
+
import { Controller } from 'stimulus'
|
3
|
+
import { castBoolean } from '@/js/helpers/cast_boolean'
|
4
|
+
|
5
|
+
export default class extends Controller {
|
6
|
+
static targets = ['input', 'controller', 'rows']
|
7
|
+
|
8
|
+
fieldValue = []
|
9
|
+
|
10
|
+
options = {}
|
11
|
+
|
12
|
+
get keyInputDisabled() {
|
13
|
+
return !this.options.editable || this.options.disable_editing_keys
|
14
|
+
}
|
15
|
+
|
16
|
+
get valueInputDisabled() {
|
17
|
+
return !this.options.editable
|
18
|
+
}
|
19
|
+
|
20
|
+
connect() {
|
21
|
+
this.setOptions()
|
22
|
+
|
23
|
+
try {
|
24
|
+
const objectValue = JSON.parse(this.inputTarget.value)
|
25
|
+
Object.keys(objectValue).forEach((key) => this.fieldValue.push([key, objectValue[key]]))
|
26
|
+
} catch (error) {
|
27
|
+
this.fieldValue = []
|
28
|
+
}
|
29
|
+
|
30
|
+
this.updateKeyValueComponent()
|
31
|
+
}
|
32
|
+
|
33
|
+
addRow() {
|
34
|
+
if (this.options.disable_adding_rows || !this.options.editable) return
|
35
|
+
this.fieldValue.push(['', ''])
|
36
|
+
this.updateKeyValueComponent()
|
37
|
+
this.focusLastRow()
|
38
|
+
}
|
39
|
+
|
40
|
+
deleteRow(event) {
|
41
|
+
if (this.options.disable_deleting_rows || !this.options.editable) return
|
42
|
+
const { index } = event.target.dataset
|
43
|
+
this.fieldValue.splice(index, 1)
|
44
|
+
this.updateTextareaInput()
|
45
|
+
this.updateKeyValueComponent()
|
46
|
+
}
|
47
|
+
|
48
|
+
focusLastRow() {
|
49
|
+
return this.rowsTarget.querySelector('.flex.key-value-row:last-child .key-value-input-key').focus()
|
50
|
+
}
|
51
|
+
|
52
|
+
valueFieldUpdated(event) {
|
53
|
+
const { value } = event.target
|
54
|
+
const { index } = event.target.dataset
|
55
|
+
this.fieldValue[index][1] = value
|
56
|
+
|
57
|
+
this.updateTextareaInput()
|
58
|
+
}
|
59
|
+
|
60
|
+
keyFieldUpdated(event) {
|
61
|
+
const { value } = event.target
|
62
|
+
const { index } = event.target.dataset
|
63
|
+
this.fieldValue[index][0] = value
|
64
|
+
|
65
|
+
this.updateTextareaInput()
|
66
|
+
}
|
67
|
+
|
68
|
+
updateTextareaInput() {
|
69
|
+
if (!this.hasInputTarget) return
|
70
|
+
let result = {}
|
71
|
+
if (this.fieldValue && this.fieldValue.length > 0) {
|
72
|
+
result = Object.assign(...this.fieldValue.map(([key, val]) => ({ [key]: val })))
|
73
|
+
}
|
74
|
+
this.inputTarget.innerText = JSON.stringify(result)
|
75
|
+
}
|
76
|
+
|
77
|
+
updateKeyValueComponent() {
|
78
|
+
let result = ''
|
79
|
+
let index = 0
|
80
|
+
this.fieldValue.forEach((row) => {
|
81
|
+
const [key, value] = row
|
82
|
+
result += this.interpolatedRow(key, value, index)
|
83
|
+
index++
|
84
|
+
})
|
85
|
+
this.rowsTarget.innerHTML = result
|
86
|
+
window.initTippy()
|
87
|
+
}
|
88
|
+
|
89
|
+
interpolatedRow(key, value, index) {
|
90
|
+
let result = `<div class="flex key-value-row">
|
91
|
+
${this.inputField('key', index, key, value)}
|
92
|
+
${this.inputField('value', index, key, value)}`
|
93
|
+
if (this.options.editable) {
|
94
|
+
result += `<a
|
95
|
+
href="javascript:void(0);"
|
96
|
+
data-index="${index}"
|
97
|
+
data-action="click->key-value#deleteRow"
|
98
|
+
title="${this.options.delete_text}"
|
99
|
+
data-tippy="tooltip"
|
100
|
+
data-button="delete-row"
|
101
|
+
tabindex="-1"
|
102
|
+
${this.options.disable_deleting_rows ? "disabled='disabled'" : ''}
|
103
|
+
class="flex items-center justify-center p-2 px-3 border-none ${this.options.disable_deleting_rows ? 'cursor-not-allowed' : ''}"
|
104
|
+
><svg class="pointer-events-none text-gray-500 h-5 hover:text-gray-500" fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" stroke="currentColor"><path d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"></path></svg></a>`
|
105
|
+
}
|
106
|
+
result += '</div>'
|
107
|
+
|
108
|
+
return result
|
109
|
+
}
|
110
|
+
|
111
|
+
inputField(id = 'key', index, key, value) {
|
112
|
+
return `<input
|
113
|
+
class="${this.options.inputClasses} !rounded-none border-gray-600 border-r border-l-0 border-b-0 border-t-0 focus:border-gray-300 w-1/2 focus:outline-none outline-none key-value-input-${id}"
|
114
|
+
data-action="input->key-value#${id}FieldUpdated"
|
115
|
+
placeholder="${this.options[`${id}_label`]}"
|
116
|
+
data-index="${index}"
|
117
|
+
${this[`${id}InputDisabled`] ? "disabled='disabled'" : ''}
|
118
|
+
value="${id === 'key' ? key : value}"
|
119
|
+
autofocus
|
120
|
+
/>`
|
121
|
+
}
|
122
|
+
|
123
|
+
setOptions() {
|
124
|
+
let fieldOptions
|
125
|
+
|
126
|
+
try {
|
127
|
+
fieldOptions = JSON.parse(this.controllerTarget.dataset.options)
|
128
|
+
} catch (error) {
|
129
|
+
fieldOptions = {}
|
130
|
+
}
|
131
|
+
this.options = {
|
132
|
+
...fieldOptions,
|
133
|
+
inputClasses: this.controllerTarget.dataset.inputClasses,
|
134
|
+
editable: castBoolean(this.controllerTarget.dataset.editable),
|
135
|
+
}
|
136
|
+
}
|
137
|
+
}
|
data/lib/avo.rb
CHANGED
@@ -3,6 +3,11 @@ require "json"
|
|
3
3
|
module Avo
|
4
4
|
module Fields
|
5
5
|
class KeyValueField < BaseField
|
6
|
+
attr_reader :key_label
|
7
|
+
attr_reader :value_label
|
8
|
+
attr_reader :action_text
|
9
|
+
attr_reader :disable_adding_rows
|
10
|
+
|
6
11
|
def initialize(name, **args, &block)
|
7
12
|
@defaults = {
|
8
13
|
partial_name: "key-value-field"
|
@@ -33,7 +38,13 @@ module Avo
|
|
33
38
|
[:"#{id}", "#{id}": {}]
|
34
39
|
end
|
35
40
|
|
36
|
-
def
|
41
|
+
def parsed_value
|
42
|
+
value.to_json
|
43
|
+
rescue
|
44
|
+
{}
|
45
|
+
end
|
46
|
+
|
47
|
+
def options
|
37
48
|
{
|
38
49
|
key_label: @key_label,
|
39
50
|
value_label: @value_label,
|
@@ -44,6 +55,18 @@ module Avo
|
|
44
55
|
disable_deleting_rows: @disable_deleting_rows
|
45
56
|
}
|
46
57
|
end
|
58
|
+
|
59
|
+
def fill_field(model, key, value)
|
60
|
+
begin
|
61
|
+
new_value = JSON.parse(value)
|
62
|
+
rescue
|
63
|
+
new_value = {}
|
64
|
+
end
|
65
|
+
|
66
|
+
model[key] = new_value
|
67
|
+
|
68
|
+
model
|
69
|
+
end
|
47
70
|
end
|
48
71
|
end
|
49
72
|
end
|
data/lib/avo/version.rb
CHANGED
@@ -6,10 +6,10 @@ module Generators
|
|
6
6
|
source_root File.expand_path("templates", __dir__)
|
7
7
|
|
8
8
|
namespace "avo:locales"
|
9
|
-
desc "
|
9
|
+
desc "Add Avo locale files to your project."
|
10
10
|
|
11
11
|
def create_files
|
12
|
-
|
12
|
+
directory File.join(__dir__, "templates", "locales"), "config/locales"
|
13
13
|
end
|
14
14
|
end
|
15
15
|
end
|
@@ -1,13 +1,9 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
class <%= class_name.camelize %> < Action
|
4
|
-
self.name = '<%= name.underscore.humanize %>'
|
1
|
+
class <%= class_name.camelize %> < Avo::BaseAction
|
2
|
+
self.name = '<%= name.underscore.humanize %>'
|
5
3
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
end
|
10
|
-
end
|
4
|
+
def handle(models:, fields:)
|
5
|
+
models.each do |model|
|
6
|
+
# Do something with your models.
|
11
7
|
end
|
12
8
|
end
|
13
9
|
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
nb:
|
2
|
+
avo:
|
3
|
+
dashboard: 'Dashboard'
|
4
|
+
choose_a_country: 'Velg et land'
|
5
|
+
choose_an_option: 'Velg et alternativ'
|
6
|
+
are_you_sure_you_want_to_run_this_option: 'Er du sikker?'
|
7
|
+
are_you_sure_detach_item: 'Er du sikker på at du vil koble fra %{item}.'
|
8
|
+
run: 'Kjør'
|
9
|
+
cancel: 'Avslutt'
|
10
|
+
action_ran_successfully: 'Suksess!'
|
11
|
+
resource_details: "%{item} detaljer: %{title}"
|
12
|
+
update_item: 'Oppdatert %{item}: %{title}'
|
13
|
+
unauthorized: 'Ikke autorisert'
|
14
|
+
attachment_class_attached: '%{attachment_class} lagt til.'
|
15
|
+
attachment_class_detached: '%{attachment_class} fjernet.'
|
16
|
+
resource_updated: 'Ressurs oppdatert'
|
17
|
+
resource_created: 'Ressurs generert'
|
18
|
+
resource_destroyed: 'Ressurs slettet'
|
19
|
+
switch_to_view: "Bytt til %{view_type} vis"
|
20
|
+
click_to_reveal_filters: "Vis filter"
|
21
|
+
attachment_destroyed: 'Vedlett slettet'
|
22
|
+
failed_to_find_attachment: 'Fant ikke vedlegg'
|
23
|
+
you_missed_something_check_form: 'Her mangler du noe. Vennligst sjekk skjemaet.'
|
24
|
+
remove_selection: 'Fjern valg'
|
25
|
+
select_item: 'Velg'
|
26
|
+
delete_file: 'Slett fil'
|
27
|
+
delete: 'slett'
|
28
|
+
delete_item: 'Slett %{item}'
|
29
|
+
download_item: 'Last ned %{item}'
|
30
|
+
download_file: 'Last ned fil'
|
31
|
+
download: 'Last ned'
|
32
|
+
view: 'Vis'
|
33
|
+
view_item: 'vis %{item}'
|
34
|
+
edit: 'endre'
|
35
|
+
edit_item: 'endre %{item}'
|
36
|
+
detach_item: 'koble fra %{item}'
|
37
|
+
number_of_items:
|
38
|
+
zero: 'ingen %{item}'
|
39
|
+
one: 'en %{item}'
|
40
|
+
other: '%{count} %{item}'
|
41
|
+
are_you_sure: 'Er du sikker?'
|
42
|
+
filters: 'Filter'
|
43
|
+
per_page: 'Per side'
|
44
|
+
more: 'Mer'
|
45
|
+
attach: 'Legg til'
|
46
|
+
cancel: 'Avslutt'
|
47
|
+
save: 'Lagre'
|
48
|
+
attach_and_attach_another: 'Legg til & Legg til ny'
|
49
|
+
hide_content: 'Skjul innhold'
|
50
|
+
show_content: 'Vis innhold'
|
51
|
+
no_related_item_found: 'Ingen relaterte %{item} funnet'
|
52
|
+
no_item_found: 'Ingen %{item} funnet'
|
53
|
+
loading: 'Laster'
|
54
|
+
confirm: 'Bekreft'
|
55
|
+
actions: 'Handlinger'
|
56
|
+
resources: 'Ressurser'
|
57
|
+
oops_nothing_found: 'Oops! Ingen ting funnet...'
|
58
|
+
type_to_search: 'Søk.'
|
59
|
+
and_x_other_resources: 'og %{count} andre ressurser'
|
60
|
+
go_back: 'Gå tilbake'
|
61
|
+
home: 'Hjem'
|
62
|
+
attach_item: 'Legg til %{item}'
|
63
|
+
choose_item: 'Velge %{item}'
|
64
|
+
create_new_item: 'Lag ny %{item}'
|
65
|
+
table_view: 'Tabell visning'
|
66
|
+
grid_view: 'Grid visning'
|
67
|
+
next_page: 'Neste side'
|
68
|
+
prev_page: 'Forrige side'
|
69
|
+
list_is_empty: 'Listen er tom'
|
70
|
+
field_translations:
|
71
|
+
file:
|
72
|
+
zero: 'filer'
|
73
|
+
one: 'fil'
|
74
|
+
other: 'filer'
|
75
|
+
resource_translations:
|
76
|
+
user:
|
77
|
+
zero: 'brukere'
|
78
|
+
one: 'bruker'
|
79
|
+
other: 'brukere'
|
80
|
+
reset_filters: 'Nullstill filter'
|
81
|
+
not_authorized: 'Du er ikke autorisert til å gjøre denne handlingen.'
|