Meet SourceLevel, an All-in-one Data & Analytics for Engineering Teams

SourceLevel provides metrics and insights by collecting data from many sources such as GitHub and GitLab. Our product brings visibility over every corner of the delivery pipeline in a Data & Analytics Solution for Engineering Teams.

Get started for free
Go to line 1
defmodule HexpmWeb.Dashboard.OrganizationView do
Go to line 2
  use HexpmWeb, :view
Go to line 3
  alias HexpmWeb.DashboardView
Go to line 5
  defp organization_roles_selector() do
Go to line 6
    Enum.map(organization_roles(), fn {name, id, _title} ->
Go to line 7
      {name, id}
Go to line 11
  defp organization_roles() do
Go to line 13
      {"Admin", "admin", "This role has full control of the organization"},
Go to line 14
      {"Write", "write", "This role has package owner access to all organization packages"},
Go to line 15
      {"Read", "read", "This role can fetch all organization packages"}
Go to line 19
  defp organization_role(id) do
Go to line 20
    Enum.find_value(organization_roles(), fn {name, organization_id, _title} ->
Go to line 21
      if id == organization_id do
Go to line 27
  defp plan("organization-monthly"), do: "Organization, monthly billed ($7.00 per user / month)"
Go to line 28
  defp plan("organization-annually"), do: "Organization, annually billed ($70.00 per user / year)"
Go to line 29
  defp plan_price("organization-monthly"), do: "$7.00"
Go to line 30
  defp plan_price("organization-annually"), do: "$70.00"
Go to line 32
  defp proration_description("organization-monthly", price, days, quantity, quantity) do
Go to line 34
    Each new seat will be prorated on the next invoice for
Go to line 35
    <strong>#{days}</strong> day(s) @ <strong>$#{money(price)}</strong>.
Go to line 40
  defp proration_description("organization-annually", price, days, quantity, quantity) do
Go to line 42
    Each new seat will be charged a proration for
Go to line 43
    <strong>#{days}</strong> day(s) @ <strong>$#{money(price)}</strong>.
Go to line 48
  defp proration_description("organization-monthly", price, days, quantity, max_period_quantity)
Go to line 49
       when quantity < max_period_quantity do
Go to line 51
    You have already used <strong>#{max_period_quantity}</strong> seats in your current billing period.
Go to line 52
    If adding seats over this amount, each new seat will be prorated on the next invoice for
Go to line 53
    <strong>#{days}</strong> day(s) @ <strong>$#{money(price)}</strong>.
Go to line 58
  defp proration_description("organization-annually", price, days, quantity, max_period_quantity)
Go to line 59
       when quantity < max_period_quantity do
Go to line 61
    You have already used <strong>#{max_period_quantity}</strong> seats in your current billing period.
Go to line 62
    If adding seats over this amount, each new seat will be charged a proration for
Go to line 63
    <strong>#{days}</strong> day(s) @ <strong>$#{money(price)}</strong>.
Go to line 68
  @no_card_message "No payment method on file"
Go to line 70
  defp payment_card(nil) do
Go to line 71
    @no_card_message
Go to line 74
  defp payment_card(%{"brand" => nil}) do
Go to line 75
    @no_card_message
Go to line 78
  defp payment_card(card) do
Go to line 79
    card_exp_month = String.pad_leading(card["exp_month"], 2, "0")
Go to line 80
    expires = "#{card_exp_month}/#{card["exp_year"]}"
Go to line 81
    "#{card["brand"]} **** **** **** #{card["last4"]}, Expires: #{expires}"
Go to line 84
  defp subscription_status(%{"status" => "active", "cancel_at_period_end" => false}, _card) do
Go to line 88
  defp subscription_status(%{"status" => "active", "cancel_at_period_end" => true}, _card) do
Go to line 89
    "Ends after current subscription period"
Go to line 92
  defp subscription_status(
Go to line 93
         %{"status" => "trialing", "trial_end" => trial_end},
Go to line 96
    trial_end = trial_end |> NaiveDateTime.from_iso8601!() |> ViewHelpers.pretty_date()
Go to line 97
    raw("Trial ends on #{trial_end}, #{trial_status_message(card)}")
Go to line 100
  defp subscription_status(%{"status" => "past_due"}, _card) do
Go to line 101
    "Active with past due invoice, if the invoice is not paid the " <>
Go to line 102
      "organization will be disabled"
Go to line 105
  defp subscription_status(%{"status" => "incomplete"}, _card) do
Go to line 109
  # TODO: Check if last invoice was unpaid and add note about it?
Go to line 110
  defp subscription_status(%{"status" => "canceled"}, _card) do
Go to line 111
    "Not active"
Go to line 114
  @trial_ends_no_card_message """
Go to line 115
  your subscription will end after the trial period because we have no payment method on file for you,
Go to line 116
  please enter a payment method if you wish to continue using organizations after the trial period
Go to line 119
  defp trial_status_message(%{"brand" => nil}) do
Go to line 120
    @trial_ends_no_card_message
Go to line 123
  defp trial_status_message(nil) do
Go to line 124
    @trial_ends_no_card_message
Go to line 127
  defp trial_status_message(_card) do
Go to line 128
    "a payment method is on file and your subscription will continue after the trial period"
Go to line 131
  defp discount_status(nil) do
Go to line 135
  defp discount_status(%{"name" => name, "percent_off" => percent_off}) do
Go to line 136
    "(\"#{name}\" discount for #{percent_off}% of price)"
Go to line 139
  defp invoice_status(%{"paid" => true}, _organization, _card), do: "Paid"
Go to line 140
  defp invoice_status(%{"status" => "uncollectible"}, _organization, _card), do: "Forgiven"
Go to line 142
  defp invoice_status(%{"paid" => false, "attempted" => false}, _organization, _card),
Go to line 143
    do: "Pending"
Go to line 145
  defp invoice_status(%{"paid" => false, "attempted" => true}, _organization, nil = _card) do
Go to line 147
      "Pay now",
Go to line 148
      class: "btn btn-primary",
Go to line 149
      disabled: true,
Go to line 150
      title: "No payment method on file"
Go to line 154
  defp invoice_status(
Go to line 155
         %{"paid" => false, "attempted" => true, "id" => invoice_id},
Go to line 156
         organization,
Go to line 159
    form_tag(Routes.organization_path(Endpoint, :pay_invoice, organization, invoice_id)) do
Go to line 160
      submit("Pay now", class: "btn btn-primary")
Go to line 164
  def payment_date(iso_8601_datetime_string) do
Go to line 165
    iso_8601_datetime_string |> NaiveDateTime.from_iso8601!() |> ViewHelpers.pretty_date()
Go to line 168
  defp money(integer) when is_integer(integer) and integer >= 0 do
Go to line 169
    whole = div(integer, 100)
Go to line 170
    float = rem(integer, 100) |> Integer.to_string() |> String.pad_leading(2, "0")
Go to line 171
    "#{whole}.#{float}"
Go to line 174
  defp default_billing_emails(user, billing_email) do
Go to line 176
      user.emails
Go to line 177
      |> Enum.filter(& &1.verified)
Go to line 178
      |> Enum.map(& &1.email)
Go to line 180
    [billing_email | emails]
Go to line 181
    |> Enum.reject(&is_nil/1)
Go to line 182
    |> Enum.uniq()
Go to line 185
  # From Hexpm.Billing.Country
Go to line 186
  @country_codes [
Go to line 187
    {"AD", "Andorra"},
Go to line 188
    {"AE", "United Arab Emirates"},
Go to line 189
    {"AF", "Afghanistan"},
Go to line 190
    {"AG", "Antigua and Barbuda"},
Go to line 191
    {"AI", "Anguilla"},
Go to line 192
    {"AL", "Albania"},
Go to line 193
    {"AM", "Armenia"},
Go to line 194
    {"AO", "Angola"},
Go to line 195
    {"AQ", "Antarctica"},
Go to line 196
    {"AR", "Argentina"},
Go to line 197
    {"AS", "American Samoa"},
Go to line 198
    {"AT", "Austria"},
Go to line 199
    {"AU", "Australia"},
Go to line 200
    {"AW", "Aruba"},
Go to line 201
    {"AX", "Åland Islands"},
Go to line 202
    {"AZ", "Azerbaijan"},
Go to line 203
    {"BA", "Bosnia and Herzegovina"},
Go to line 204
    {"BB", "Barbados"},
Go to line 205
    {"BD", "Bangladesh"},
Go to line 206
    {"BE", "Belgium"},
Go to line 207
    {"BF", "Burkina Faso"},
Go to line 208
    {"BG", "Bulgaria"},
Go to line 209
    {"BH", "Bahrain"},
Go to line 210
    {"BI", "Burundi"},
Go to line 211
    {"BJ", "Benin"},
Go to line 212
    {"BL", "Saint Barthélemy"},
Go to line 213
    {"BM", "Bermuda"},
Go to line 214
    # Brunei Darussalam
Go to line 215
    {"BN", "Brunei"},
Go to line 216
    # Bolivia, Plurinational State
Go to line 217
    {"BO", "Bolivia"},
Go to line 218
    # Bonaire, Sint Eustatius and Saba
Go to line 219
    {"BQ", "Bonaire"},
Go to line 220
    {"BR", "Brazil"},
Go to line 221
    {"BS", "Bahamas"},
Go to line 222
    {"BT", "Bhutan"},
Go to line 223
    {"BV", "Bouvet Island"},
Go to line 224
    {"BW", "Botswana"},
Go to line 225
    {"BY", "Belarus"},
Go to line 226
    {"BZ", "Belize"},
Go to line 227
    {"CA", "Canada"},
Go to line 228
    {"CC", "Cocos (Keeling) Islands"},
Go to line 229
    {"CD", "Congo, the Democratic Republic of the"},
Go to line 230
    {"CF", "Central African Republic"},
Go to line 231
    {"CG", "Congo"},
Go to line 232
    {"CH", "Switzerland"},
Go to line 233
    {"CI", "Côte d'Ivoire"},
Go to line 234
    {"CK", "Cook Islands"},
Go to line 235
    {"CL", "Chile"},
Go to line 236
    {"CM", "Cameroon"},
Go to line 237
    {"CN", "China"},
Go to line 238
    {"CO", "Colombia"},
Go to line 239
    {"CR", "Costa Rica"},
Go to line 240
    {"CU", "Cuba"},
Go to line 241
    {"CV", "Cabo Verde"},
Go to line 242
    {"CW", "Curaçao"},
Go to line 243
    {"CX", "Christmas Island"},
Go to line 244
    {"CY", "Cyprus"},
Go to line 245
    # Czechia (Changed for Stripe compatibility)
Go to line 246
    {"CZ", "Czech Republic"},
Go to line 247
    {"DE", "Germany"},
Go to line 248
    {"DJ", "Djibouti"},
Go to line 249
    {"DK", "Denmark"},
Go to line 250
    {"DM", "Dominica"},
Go to line 251
    {"DO", "Dominican Republic"},
Go to line 252
    {"DZ", "Algeria"},
Go to line 253
    {"EC", "Ecuador"},
Go to line 254
    {"EE", "Estonia"},
Go to line 255
    {"EG", "Egypt"},
Go to line 256
    {"EH", "Western Sahara"},
Go to line 257
    {"ER", "Eritrea"},
Go to line 258
    {"ES", "Spain"},
Go to line 259
    {"ET", "Ethiopia"},
Go to line 260
    {"FI", "Finland"},
Go to line 261
    {"FJ", "Fiji"},
Go to line 262
    # Falkland Islands (Malvinas)
Go to line 263
    {"FK", "Falkland Island"},
Go to line 264
    # Micronesia, Federated States of
Go to line 265
    {"FM", "Micronesia"},
Go to line 266
    {"FO", "Faroe Islands"},
Go to line 267
    {"FR", "France"},
Go to line 268
    {"GA", "Gabon"},
Go to line 269
    # United Kingdom of Great Britain and Northern Ireland
Go to line 270
    {"GB", "United Kingdom"},
Go to line 271
    {"GD", "Grenada"},
Go to line 272
    {"GE", "Georgia"},
Go to line 273
    {"GF", "French Guiana"},
Go to line 274
    {"GG", "Guernsey"},
Go to line 275
    {"GH", "Ghana"},
Go to line 276
    {"GI", "Gibraltar"},
Go to line 277
    {"GL", "Greenland"},
Go to line 278
    {"GM", "Gambia"},
Go to line 279
    {"GN", "Guinea"},
Go to line 280
    {"GP", "Guadeloupe"},
Go to line 281
    {"GQ", "Equatorial Guinea"},
Go to line 282
    {"GR", "Greece"},
Go to line 283
    # South Georgia and the South Sandwich Islands
Go to line 284
    {"GS", "South Georgia"},
Go to line 285
    {"GT", "Guatemala"},
Go to line 286
    {"GU", "Guam"},
Go to line 287
    {"GW", "Guinea-Bissau"},
Go to line 288
    {"GY", "Guyana"},
Go to line 289
    {"HK", "Hong Kong"},
Go to line 290
    {"HM", "Heard Island and McDonald Islands"},
Go to line 291
    {"HN", "Honduras"},
Go to line 292
    {"HR", "Croatia"},
Go to line 293
    {"HT", "Haiti"},
Go to line 294
    {"HU", "Hungary"},
Go to line 295
    {"ID", "Indonesia"},
Go to line 296
    {"IE", "Ireland"},
Go to line 297
    {"IL", "Israel"},
Go to line 298
    {"IM", "Isle of Man"},
Go to line 299
    {"IN", "India"},
Go to line 300
    {"IO", "British Indian Ocean Territory"},
Go to line 301
    {"IQ", "Iraq"},
Go to line 302
    # Iran, Islamic Republic
Go to line 303
    {"IR", "Iran"},
Go to line 304
    {"IS", "Iceland"},
Go to line 305
    {"IT", "Italy"},
Go to line 306
    {"JE", "Jersey"},
Go to line 307
    {"JM", "Jamaica"},
Go to line 308
    {"JO", "Jordan"},
Go to line 309
    {"JP", "Japan"},
Go to line 310
    {"KE", "Kenya"},
Go to line 311
    {"KG", "Kyrgyzstan"},
Go to line 312
    {"KH", "Cambodia"},
Go to line 313
    {"KI", "Kiribati"},
Go to line 314
    {"KM", "Comoros"},
Go to line 315
    {"KN", "Saint Kitts and Nevis"},
Go to line 316
    {"KP", "Korea, Democratic People's Republic of"},
Go to line 317
    {"KR", "Korea, Republic of"},
Go to line 318
    {"KW", "Kuwait"},
Go to line 319
    {"KY", "Cayman Islands"},
Go to line 320
    {"KZ", "Kazakhstan"},
Go to line 321
    # Lao People's Democratic Republic
Go to line 322
    {"LA", "Laos"},
Go to line 323
    {"LB", "Lebanon"},
Go to line 324
    {"LC", "Saint Lucia"},
Go to line 325
    {"LI", "Liechtenstein"},
Go to line 326
    {"LK", "Sri Lanka"},
Go to line 327
    {"LR", "Liberia"},
Go to line 328
    {"LS", "Lesotho"},
Go to line 329
    {"LT", "Lithuania"},
Go to line 330
    {"LU", "Luxembourg"},
Go to line 331
    {"LV", "Latvia"},
Go to line 332
    {"LY", "Libya"},
Go to line 333
    {"MA", "Morocco"},
Go to line 334
    {"MC", "Monaco"},
Go to line 335
    {"MD", "Moldova , Republic"},
Go to line 336
    {"ME", "Montenegro"},
Go to line 337
    # Saint Martin (French part)
Go to line 338
    {"MF", "Saint Martin"},
Go to line 339
    {"MG", "Madagascar"},
Go to line 340
    {"MH", "Marshall Islands"},
Go to line 341
    {"MK", "Macedonia"},
Go to line 342
    {"ML", "Mali"},
Go to line 343
    {"MM", "Myanmar"},
Go to line 344
    {"MN", "Mongolia"},
Go to line 345
    {"MO", "Macao"},
Go to line 346
    {"MP", "Northern Mariana Islands"},
Go to line 347
    {"MQ", "Martinique"},
Go to line 348
    {"MR", "Mauritania"},
Go to line 349
    {"MS", "Montserrat"},
Go to line 350
    {"MT", "Malta"},
Go to line 351
    {"MU", "Mauritius"},
Go to line 352
    {"MV", "Maldives"},
Go to line 353
    {"MW", "Malawi"},
Go to line 354
    {"MX", "Mexico"},
Go to line 355
    {"MY", "Malaysia"},
Go to line 356
    {"MZ", "Mozambique"},
Go to line 357
    {"NA", "Namibia"},
Go to line 358
    {"NC", "New Caledonia"},
Go to line 359
    {"NE", "Niger"},
Go to line 360
    {"NF", "Norfolk Island"},
Go to line 361
    {"NG", "Nigeria"},
Go to line 362
    {"NI", "Nicaragua"},
Go to line 363
    {"NL", "Netherlands"},
Go to line 364
    {"NO", "Norway"},
Go to line 365
    {"NP", "Nepal"},
Go to line 366
    {"NR", "Nauru"},
Go to line 367
    {"NU", "Niue"},
Go to line 368
    {"NZ", "New Zealand"},
Go to line 369
    {"OM", "Oman"},
Go to line 370
    {"PA", "Panama"},
Go to line 371
    {"PE", "Peru"},
Go to line 372
    {"PF", "French Polynesia"},
Go to line 373
    {"PG", "Papua New Guinea"},
Go to line 374
    {"PH", "Philippines"},
Go to line 375
    {"PK", "Pakistan"},
Go to line 376
    {"PL", "Poland"},
Go to line 377
    {"PM", "Saint Pierre and Miquelon"},
Go to line 378
    {"PN", "Pitcairn"},
Go to line 379
    {"PR", "Puerto Rico"},
Go to line 380
    # Palestine, State of
Go to line 381
    {"PS", "Palestin"},
Go to line 382
    {"PT", "Portugal"},
Go to line 383
    {"PW", "Palau"},
Go to line 384
    {"PY", "Paraguay"},
Go to line 385
    {"QA", "Qatar"},
Go to line 386
    {"RE", "Réunion"},
Go to line 387
    {"RO", "Romania"},
Go to line 388
    {"RS", "Serbia"},
Go to line 389
    # Russian Federation
Go to line 390
    {"RU", "Russia"},
Go to line 391
    {"RW", "Rwanda"},
Go to line 392
    {"SA", "Saudi Arabia"},
Go to line 393
    {"SB", "Solomon Islands"},
Go to line 394
    {"SC", "Seychelles"},
Go to line 395
    {"SD", "Sudan"},
Go to line 396
    {"SE", "Sweden"},
Go to line 397
    {"SG", "Singapore"},
Go to line 398
    {"SH", "Saint Helena, Ascension and Tristan da Cunha"},
Go to line 399
    {"SI", "Slovenia"},
Go to line 400
    {"SJ", "Svalbard and Jan Mayen"},
Go to line 401
    {"SK", "Slovakia"},
Go to line 402
    {"SL", "Sierra Leone"},
Go to line 403
    {"SM", "San Marino"},
Go to line 404
    {"SN", "Senegal"},
Go to line 405
    {"SO", "Somalia"},
Go to line 406
    {"SR", "Suriname"},
Go to line 407
    {"SS", "South Sudan"},
Go to line 408
    {"ST", "Sao Tome and Principe"},
Go to line 409
    {"SV", "El Salvador"},
Go to line 410
    # Sint Maarten (Dutch part)
Go to line 411
    {"SX", "Sint Maarten"},
Go to line 412
    # Syrian Arab Republic
Go to line 413
    {"SY", "Syria"},
Go to line 414
    {"SZ", "Swaziland"},
Go to line 415
    {"TC", "Turks and Caicos Islands"},
Go to line 416
    {"TD", "Chad"},
Go to line 417
    {"TF", "French Southern Territories"},
Go to line 418
    {"TG", "Togo"},
Go to line 419
    {"TH", "Thailand"},
Go to line 420
    {"TJ", "Tajikistan"},
Go to line 421
    {"TK", "Tokelau"},
Go to line 422
    {"TL", "Timor-Leste"},
Go to line 423
    {"TM", "Turkmenistan"},
Go to line 424
    {"TN", "Tunisia"},
Go to line 425
    {"TO", "Tonga"},
Go to line 426
    {"TR", "Turkey"},
Go to line 427
    {"TT", "Trinidad and Tobago"},
Go to line 428
    {"TV", "Tuvalu"},
Go to line 429
    # Taiwan, Province of China
Go to line 430
    {"TW", "Taiwan"},
Go to line 431
    # Tanzania, United Republic of
Go to line 432
    {"TZ", "Tanzania"},
Go to line 433
    {"UA", "Ukraine"},
Go to line 434
    {"UG", "Uganda"},
Go to line 435
    {"UM", "United States Minor Outlying Islands"},
Go to line 436
    # United States of America
Go to line 437
    {"US", "United States"},
Go to line 438
    {"UY", "Uruguay"},
Go to line 439
    {"UZ", "Uzbekistan"},
Go to line 440
    {"VA", "Holy See"},
Go to line 441
    {"VC", "Saint Vincent and the Grenadines"},
Go to line 442
    # Venezuela, Bolivarian Republic of
Go to line 443
    {"VE", "Venezuela"},
Go to line 444
    # Virgin Islands, British
Go to line 445
    {"VG", "British Virgin Islands"},
Go to line 446
    # Virgin Islands, U.S.
Go to line 447
    {"VI", "United States Virgin Islands"},
Go to line 448
    {"VN", "Viet Nam"},
Go to line 449
    {"VU", "Vanuatu"},
Go to line 450
    {"WF", "Wallis and Futuna"},
Go to line 451
    {"WS", "Samoa"},
Go to line 452
    {"YE", "Yemen"},
Go to line 453
    {"YT", "Mayotte"},
Go to line 454
    {"ZA", "South Africa"},
Go to line 455
    {"ZM", "Zambia"},
Go to line 456
    {"ZW", "Zimbabwe"}
Go to line 459
  defp countries() do
Go to line 460
    unquote([{"", ""}] ++ Enum.sort_by(@country_codes, &elem(&1, 1)))
Go to line 463
  defp show_person?(person, errors) do
Go to line 464
    (person || errors["person"]) && !errors["company"]
Go to line 467
  defp show_company?(company, errors) do
Go to line 468
    (company || errors["company"]) && !errors["person"]
Go to line 471
  defp organization_admin?(current_user, organization) do
Go to line 472
    user = Enum.find(organization.organization_users, &(&1.user_id == current_user.id))
Go to line 473
    user.role == "admin"