Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ RuboCop::RakeTask.new

desc 'Run Cucumber features'
task :cucumber do
sh 'cucumber --format pretty'
sh 'bundle exec cucumber --format pretty'
end

task default: %i[rubocop test cucumber]
12 changes: 12 additions & 0 deletions features/project_list.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
Feature: Project List
As a user
I want to list projects
So that I can see what projects are available

Scenario: Listing my projects
When I run `lc project list --mine`
Then the output should match /Crying Game/

Scenario: Listing all projects
When I run `lc project list`
Then the output should match /Crying Game/
22 changes: 22 additions & 0 deletions lib/linear/commands/project.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# frozen_string_literal: true

require_relative '../cli/sub_commands'

module Rubyists
module Linear
module CLI
# The Project module is the namespace for all project-related commands
module Project
include CLI::SubCommands

# Aliases for Project commands.
ALIASES = {
list: %w[ls l], # aliases for the list command
project: %w[p projects] # aliases for the main project command itself
}.freeze

DESCRIPTION = 'Manage projects'
end
end
end
end
38 changes: 38 additions & 0 deletions lib/linear/commands/project/list.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# frozen_string_literal: true

require 'semantic_logger'

module Rubyists
# Main module for Linear CLI commands
module Linear
M :project
O 'project/list'
module CLI
module Project
List = Class.new Dry::CLI::Command
# The List class is a Dry::CLI::Command that lists projects
class List
include SemanticLogger::Loggable
include Rubyists::Linear::CLI::CommonOptions

desc 'List projects'
example [
' # List all projects',
'--mine # List only my projects'
]
option :mine, type: :boolean, default: false, desc: 'Only show my projects'

def call(**options)
logger.debug 'Listing projects'
result = Rubyists::Linear::Operations::Project::List.call(params: options)
if result.success?
display result[:projects], options
else
logger.error 'Failed to list projects'
end
end
end
end
end
end
end
8 changes: 8 additions & 0 deletions lib/linear/models/project.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ class Project
updatedAt
end

def self.mine
User.me.teams.flat_map(&:projects)
end

def slug
File.basename(url).sub("-#{slugId}", '')
end
Expand Down Expand Up @@ -49,6 +53,10 @@ def to_s
def inspection
format('name: "%<name>s" type: "%<url>s"', name:, url:)
end

def display(_options)
printf "%s\n", to_s
end
end
end
end
17 changes: 17 additions & 0 deletions lib/linear/models/team.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,23 @@ class Team
include SemanticLogger::Loggable

one_to_many :projects
alias loaded_projects projects

def projects # rubocop:disable Metrics/MethodLength
return @projects if @projects
return @projects = loaded_projects if loaded_projects

team_id = data[:id]
q = query do
team(id: team_id) do
projects(first: 100) do
nodes { ___ Project.base_fragment }
end
end
end
data = Api.query(q)
@projects = data.dig(:team, :projects, :nodes)&.map { |project| Project.new project } || []
end

# TODO: Make this configurable
BaseFilter = { # rubocop:disable Naming/ConstantName
Expand Down
22 changes: 22 additions & 0 deletions lib/linear/operations/project/list.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# frozen_string_literal: true

module Rubyists
module Linear
module Operations
module Project
# The List operation lists projects
class List < Trailblazer::Operation
step :fetch_projects

def fetch_projects(ctx, params:, **)
ctx[:projects] = if params[:mine]
Rubyists::Linear::Project.mine
else
Rubyists::Linear::Project.all
end
end
end
end
end
end
end
1 change: 1 addition & 0 deletions linear-cli.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ Gem::Specification.new do |spec|
spec.add_dependency 'git'
spec.add_dependency 'gqli'
spec.add_dependency 'httpx'
spec.add_dependency 'ostruct'
spec.add_dependency 'pry-byebug'
spec.add_dependency 'reline'
spec.add_dependency 'semantic_logger'
Expand Down
36 changes: 36 additions & 0 deletions test/linear/operations/project/list_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# frozen_string_literal: true

require_relative '../../../test_helper'
require 'linear/operations/project/list'

class ProjectListOperationTest < Minitest::Spec
describe 'Rubyists::Linear::Operations::Project::List' do
let(:projects) { [Object.new, Object.new] }

describe 'when mine is true' do
let(:params) { { mine: true } }

it 'fetches my projects' do
Rubyists::Linear::Project.stub :mine, projects do
result = Rubyists::Linear::Operations::Project::List.call(params: params)

_(result.success?).must_equal true
_(result[:projects]).must_equal projects
end
end
end

describe 'when mine is false' do
let(:params) { { mine: false } }

it 'fetches all projects' do
Rubyists::Linear::Project.stub :all, projects do
result = Rubyists::Linear::Operations::Project::List.call(params: params)

_(result.success?).must_equal true
_(result[:projects]).must_equal projects
end
end
end
end
end
Loading