How to display current_admin_user's name in navigation header? - ruby-on-rails-4

Construction like:
menu.add :label => current_admin_user.full_name do |submenu|
menus.each do |m|
submenu.add :label => m['name'],
:url => "/admin/change/#{m['id']}",
:html_options => {:style => 'float:left;'},
:if => proc { current_admin_user.role?('super_admin') }
end
end
Doesn't work in 1.0pre+ anymore. There is no current_admin_user in the scope. But in the logs i see the request that fetches admin user before a menu getting added.
SELECT `admin_users`.* FROM `admin_users` WHERE `admin_users`.`id` = 6 ORDER BY `admin_users`.`id` ASC LIMIT 1
Any chance to deal with it?

It is still possible to use, i only needed to pass id of a menu
menu.add id: 'user_name' label: -> { current_admin_user.full_name } do |submenu|

Related

NgRx how to dispatch 2 actions in order

I cant seem to find a way with the NgRx (not RxJS Style) to dispatch 2 Actions in an effect.
I would like to (IN THIS ORDER):
delete a Movie in the Database with an effect,
dispatch deleteMovieSuccess
dispatch getMovies (I need to reload all Movies afterwards!)
I tried to do it like below, but it just fires the first Action, and I cannot see the other action:
In my log I can see:
[Movie list] Delete movie
[Movie list] Get movies
[Movie list] Get movies successful
I have the folloing actions:
export const getMovies = createAction('[Movie List] Get Movies', props<{search: string, page: number, limit: number}>());
export const getMoviesSuccess = createAction('[Movies List] Get Movies Success', props<{ search: string, page: number, limit: number }>());
export const deleteMovie = createAction('[Movie List] Remove Movie', props<{ movieToDelete: Movie, search: string, page: number, limit: number }>());
export const deleteMovieSuccess = createAction('[Movie List] Remove Movie Success', props<{ movieToDelete: Movie }>());
and the following effect:
deleteMovie$ = createEffect(() => this.actions$.pipe(
ofType(MovieActions.deleteMovie),
mergeMap(({movieToDelete, search, page, limit}) =>
this.moviesService.deleteMovie(movieToDelete)
.pipe(
map(() => MovieActions.deleteMovieSuccess({movieToDelete: movieToDelete})),
map(() => MovieActions.getMovies({search, page, limit})),
catchError(() => EMPTY)
)
)
)
);
How can I trigger BOTH, deleteMoviesSuccess, and getMovies in this order?
I`ve also tried with switchMap and and faltMap, but never are both Actions dispatched correctly.
I just cant seem to understand, how dispatching in an iterative way is possible, but I really need it for my special usecase.
Any help is greatly appreciated.
You should not dispatch two action in as a result of an effect. Rather dispatch some kind of success action and then react on that in other effects. Read here
You could create a chain of effect:
dispatch delete action
on finish of delete dispatch deleteSuccess action
on deleteSuccess action trigger loadMovies effect
on loadMovies success some set action for a reducer to pick up
deleteMovie$ = createEffect(() => this.actions$.pipe(
ofType(MovieActions.deleteMovie),
mergeMap(({movieToDelete, search, page, limit}) => this.moviesService.deleteMovie(movieToDelete).pipe(
map(() => MovieActions.deleteMovieSuccess({movieToDelete: movieToDelete})),
catchError(() => EMPTY)
))
));
loadMovie$ = createEffect(() => this.actions$.pipe(
ofType(MovieActions.deleteMovieSuccess),
mergeMap(() => this.moviesService.loadMovies().pipe(
map(movies => MovieActions.setMovies({ movies })),
catchError(() => EMPTY)
))
));
EDIT
Also instead of passing parameters like limit or search you may hold these in the store. Doing so gives you the advantage to always access those in effects when needed. The NgRx Documentation has a great example on how this selecting in an effect is done. ngrx.io/api/effects/concatLatestFrom
you could use the switchMap operator to return an array of actions.
For example, instead of;
deleteMovie$ = createEffect(() => this.actions$.pipe(
ofType(MovieActions.deleteMovie),
mergeMap(({movieToDelete, search, page, limit}) =>
this.moviesService.deleteMovie(movieToDelete)
.pipe(
map(() => MovieActions.deleteMovieSuccess({movieToDelete: movieToDelete})),
map(() => MovieActions.getMovies({search, page, limit})),
catchError(() => EMPTY)
)
)
)
);
You could try;
deleteMovie$ = createEffect(() => this.actions$.pipe(
ofType(MovieActions.deleteMovie),
mergeMap(({movieToDelete, search, page, limit}) =>
this.moviesService.deleteMovie(movieToDelete)
.pipe(
switchMap(() => [MovieActions.deleteMovieSuccess({movieToDelete: movieToDelete}),
MovieActions.getMovies({search, page, limit})]),
catchError(() => EMPTY)
)
)
)
);

In Rails4 app, integrating Stripe, but Stripe says "Received unknown parameter: type"

UPDATE:
Ah! This fixed it:
stripe_account = Stripe::Account.create(
{
:legal_entity => { :type => "company" },
:country => "US",
:managed => true
}
)
In our Rails4 app we are trying to integrate Stripe. We are building an auction site, and we will use Stripe to both charge customers and then also send the money to the sellers.
We set up the pages that deal with charging, and everything works great on that side. Customers can make a purchase. We auth their cards, and then, when the seller delivers the product, we capture the charge. 100% perfection.
However, I have run into problems when I try to create the managed accounts for the sellers. This was working fine:
stripe_account = Stripe::Account.create(
{
:country => "US",
:managed => true
}
)
But the documentation says that I need to specify whether the seller is an individual or a company, so I did:
stripe_account = Stripe::Account.create(
{
:type => "company",
:country => "US",
:managed => true
}
)
And now I get this error:
Stripe::InvalidRequestError in Supplier::ProfilesController#new
Received unknown parameter: type
If I look here:
https://stripe.com/docs/api#create_account
I see:
type
string
Either “individual” or “company”, for what kind of legal entity the account owner is for
So why is this an error?
UPDATE:
Ah! This fixed it:
stripe_account = Stripe::Account.create(
{
:legal_entity => { :type => "company" },
:country => "US",
:managed => true
}
)
Ah! This fixed it:
stripe_account = Stripe::Account.create(
{
:legal_entity => { :type => "company" },
:country => "US",
:managed => true
}
)

how to edit menu bar in active admin? - change the language. Rails

I'm using Active Admin with i18n. Everything works but if i want to change language I need to do that by hand - changing site address :-(... How to add buttons in navigate bar with models names? It could be another place but good for that - accessible.
You can set a default locale in a before filter by adding the following lines to application_controller.rb:
before_filter :set_locale
def set_locale
I18n.locale = params[:locale] || I18n.default_locale
end
def default_url_options(options={})
{ :locale => I18n.locale }
end
Add a menu for selecting languages in active_admin.rb:
config.namespace :admin do |admin|
admin.build_menu :utility_navigation do |menu|
menu.add :label => "Languages" do |lang|
lang.add :label => "English",:url => proc { url_for(:locale => 'en') }, id: 'i18n-en', :priority => 1
lang.add :label => "Mexican",:url => proc { url_for(:locale => 'es') }, id: 'i18n-es', :priority => 2
end
menu.add :label => proc { display_name current_active_admin_user },
:url => '#',
:id => 'current_user',
:if => proc { current_active_admin_user? }
admin.add_logout_button_to_menu menu
end
end
You can set the default locale in application.rb:
config.before_configuration do
I18n.load_path += Dir[Rails.root.join('config', 'locales', '*.{rb,yml}').to_s]
I18n.default_locale = :en
I18n.reload!
end

bootstrap typehead dropdown doesn't expand over bootstrap collapse

So I have bootstrap collapse and inside it I have tabs, and inside one of the tabs I have a form with text_field that has bootstrap typeahead and the problem is that typeahead's dropdown dosn't expand over collapse.
that text_field with autocomplete is the last element in there.
here is the picture.
I want that dropdown expands below the collapse element (below the line on the picture)
EDIT:
Here is the haml for that view
- #i = 0
- #trainings.each do |training|
- #i = #i+1
.accordion#accordion2
.accordion-group
.accordion-heading
%a{:class => 'accordion-toggle', 'data-toggle' => 'collapse', :href => "#collapse#{#i}"}
= "Training #{#i}"
%div{:id => "collapse#{#i}", :class => 'accordion-body collapse'}
.accordion-inner
%pre= "Description: #{training.description}"
%ul.nav.nav-tabs#myTab
%li.active
%a{"data-toggle" => "tab", :href => "#planirano#{#i}"} Planirano
%li
%a{"data-toggle" => "tab", :href => "#napravljeno#{#i}"} Napravljeno
.tab-content
%div{:class => 'tab-pane active', :id => "planirano#{#i}"}
- training.exercises.each do |exercise|
%pre= "#{exercise.element.name} | #{exercise.description} | #{exercise.number_of_series}"
= form_for :training_exercise, :url => training_exercises_path(:training => training.id), remote: true, html: {:class => 'form-inline'} do |f|
= f.label :exercise
= f.text_field :exercise, :id => 'add_training_exercise'
= f.button :Add, :class => 'btn'
%div{:class => 'tab-pane', :id => "napravljeno#{#i}"} to sam napravio
f.text_ifeld :exercise, :id => 'add_training_exercise' is the field with autocomplete I am asking about.
EDIT:
and here is the rendered HTML
I somehow find the answer on stack overflow the solution is
.accordion-body.in { overflow:visible; }
It is from here.
I am sorry for asking question that already has the answer but I really was not able to find it because I didn't guess the right word for searching.
Applying the following css works only partially, accordion-body.in { overflow:visible; }, since it only displays the overflow of the "slice" that is being expanded. You'd need to apply it to the parent as well. In addition the above css affects the expand/collapse effect; i.e. the content of what is being shown get's displayed over the accordion, versus gradually being shown. A solution I tried is to:
1. Apply the overflow:visible only to the parent, i.e. #myAccordion { overflow:visible } AND
2. Apply overflow:visible only to the "slice" being opened when it is needed (on open), and removing it on close, like so:
$("#myAccordion").collapse();
// Here, we are attaching event handlers to the accordion "slice" body so that we can update it's overflow when opened AND when it's about to be closed.
$("#myAccordion .accordion-body").on("shown", function () {
$(this).css("overflow", "visible");
});
$("#myAccordion .accordion-body").on("hide", function () {
$(this).css("overflow", "hidden");
});
This worked for me since my typeahead is in a navbar
.navbar-collapse.in{
/*allows typeahead to overflow nav bar during collapse*/
overflow-y:initial !important;
}

kendo grid foreign key on Addition

I am able to use Foreign Key column in a Kendo Grid. Using inline editing method, the "edit" action is working fine.
However, when adding a new record, every thing is fine on display. The foreign key column allows me to select value. But clicking the update button, the foreign key column value is null and subsequently unable to update database in my case.
Any advise how to resolve this.
I had same problem, Kendo UI isn't resolved problem yet (15/08/2014).
I resolved adding a client event on grid:
#(Html.Kendo().Grid<SPDProject.Models.DTO.ProyectoDTO>()
.Name("GridProyectos")
.Columns(columns =>
{
columns.Bound(r => r.Id).Visible(false);
columns.Bound(r => r.Nombre).Width(150);
columns.Bound(r => r.Alias).Width(150);
columns.ForeignKey(r => r.IdCliente, (System.Collections.IEnumerable)ViewData["IdCliente_Data"], "Value", "Text");
columns.ForeignKey(r => r.IdTipoProyecto, (System.Collections.IEnumerable)ViewData["IdTipoProyecto_Data"], "Value", "Text");
columns.Command(command => { command.Edit(); command.Destroy(); }).Width(172);
})
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(10)
.Events(events => events.Error("error_handler"))
.Create(create => create.Action("CreateProyecto", "Admin"))
.Destroy(destroy => destroy.Action("DestroyProyecto", "Admin"))
.Model(model => model.Id(r => r.Id))
.Read(read => read.Action("ReadProyecto", "Admin"))
.Update(update => update.Action("UpdateProyecto", "Admin")))
.Editable(editable => editable.Mode(GridEditMode.InLine))
.Pageable(pageable => pageable.Refresh(true))
.Reorderable(reorderable => reorderable.Columns(true))
.Events(events => events.Save("onSave"))
.Resizable(resizable => resizable.Columns(true))
.Scrollable(scrollable => scrollable.Height(250))
.Selectable(selectable => selectable.Mode(GridSelectionMode.Multiple).Type(GridSelectionType.Row))
.Sortable(sortable => sortable.AllowUnsort(true).SortMode(GridSortMode.MultipleColumn))
.ToolBar(toolBar => toolBar.Create()))
<script type="text/javascript">
function onSave(e) {
//set the value to the model
e.model.set('IdCliente', $('#IdCliente').val());
e.model.set('IdTipoProyecto', $('#IdTipoProyecto').val());
}
I hope this helps somebody.
Regards,
Mauro at DreamSys